界面统一管理、观察者设计模式
2014-10-08 14:25
477 查看
界面统一管理
利用一个Activity去管理应用中所有的界面——速度快。
界面管理实现:
1)抽取标题管理
2)抽取底部导航管理
3)抽取中间内容部分管理,建立内容部分切换机制
4)完善用户提示机制
标题、底部导航等变化不多的部分分别写布局文件,然后在Activity引入的布局文件中用include方法包括这些布局文件。中间部分等变化多的先用一个相对布局占着位置。然后再写各自的管理者。标题管理者和底部导航管理者思路一致,主要功能描述:
①管理对象的创建(用单例模式)
②初始化各个标题容器及相关控件设置监听
③控制各个标题容器的显示和隐藏
④控制标题内容显示
如:
由于该类中有findViewById的初始化操作,所以,在Activity的onCreate方法中必须调用上面的init()方法。如:
界面切换
界面切换的核心方法是ViewGroup的addView和removeView方法。
首先为中间部分的界面写一个抽象的基类BaseUI,并在类中写获得需要在中间容器中加载的内容的方法。中间部分的界面都继承该基类。
中间显示内容例子:
之前在类中用View.inflate(context, resource, root);使布局文件转换成View对象时,都是设置root为null,这次设置为null时,显示效果有问题,产生原因是:
root为null时,view.getLayoutParams()为null,源码中布局参数为空时,没有设置view的宽高信息,所以这里需要我们自己设置view的宽高信息。
之前在Listview中设置root为null,却没有出现显示效果的问题,是因为Listview的源码中给自己的子孩子都设置了宽高信息。
在中间部分管理者中写changeUI()的方法。在该方法中用removeView()(或removeAllViews())和addView()方法切换界面。
然后在Activity中findViewById找到中间部分占着位置的相对布局,并把该布局传递给管理者。
观察者设计模式
①被观察者继承Observable,观察者实现Observer接口。
②Activity初始化时建立观察者和被观察者之间的关系。
③当观察者变化时通知被观察者。被观察者做出相应的响应。
利用一个Activity去管理应用中所有的界面——速度快。
界面管理实现:
1)抽取标题管理
2)抽取底部导航管理
3)抽取中间内容部分管理,建立内容部分切换机制
4)完善用户提示机制
标题、底部导航等变化不多的部分分别写布局文件,然后在Activity引入的布局文件中用include方法包括这些布局文件。中间部分等变化多的先用一个相对布局占着位置。然后再写各自的管理者。标题管理者和底部导航管理者思路一致,主要功能描述:
①管理对象的创建(用单例模式)
②初始化各个标题容器及相关控件设置监听
③控制各个标题容器的显示和隐藏
④控制标题内容显示
如:
<span style="font-size:18px;">/** * 标题容器的管理者,实现Observer接口是作为观察者 * * @author HP1 * */ public class TitleManager implements Observer{ // ①管理对象的创建(用单例模式) private static TitleManager instance = new TitleManager(); private TitleManager(){ } public static TitleManager getInstance() { return instance; } private RelativeLayout commonContainer; private RelativeLayout unLoginContainer; private RelativeLayout loginContainer; private ImageView goback;// 返回 private ImageView help;// 帮助 private ImageView login;// 登录 private TextView titleContent;// 标题内容 private TextView userInfo;// 用户信息 public void init(Activity activity){// ②初始化各个标题容器及相关控件设置监听 commonContainer = (RelativeLayout) activity.findViewById(R.id.ii_common_container); unLoginContainer = (RelativeLayout) activity.findViewById(R.id.ii_unlogin_title); loginContainer = (RelativeLayout) activity.findViewById(R.id.ii_login_title); goback = (ImageView) activity.findViewById(R.id.ii_title_goback); help = (ImageView) activity.findViewById(R.id.ii_title_help); login = (ImageView) activity.findViewById(R.id.ii_title_login); titleContent = (TextView) activity.findViewById(R.id.ii_title_content); userInfo = (TextView) activity.findViewById(R.id.ii_top_user_info); setListener(); } private void setListener() { goback.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.out.println("返回键"); } }); help.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.out.println("help"); } }); login.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.out.println("login"); MiddleManager.getInstance().changeUI(SecondUI.class); } }); } <span style="white-space:pre"> </span>// ③控制各个标题容器的显示和隐藏 private void initTitle(){ commonContainer.setVisibility(View.GONE); unLoginContainer.setVisibility(View.GONE); loginContainer.setVisibility(View.GONE); } /** * 显示通用标题 */ public void showCommonTitle() { initTitle(); commonContainer.setVisibility(View.VISIBLE); } /** * 显示未登录标题 */ public void showUnloginTitle() { initTitle(); unLoginContainer.setVisibility(View.VISIBLE); } /** * 显示已登陆标题 */ public void showLoginTitle() { initTitle(); loginContainer.setVisibility(View.VISIBLE); } // ④控制标题内容显示 public void changeTitle(String title){ titleContent.setText(title); } /** * 收到被观察者的通知时调用此方法,data是被观察者传递的信息,这里是界面的id值 */ @Override public void update(Observable observable, Object data) { if(data != null){ Integer id = Integer.valueOf(data.toString()); switch (id) { case ConstantValue.FIRSTUI: showCommonTitle(); break; case ConstantValue.SECONDUI: showUnloginTitle(); break; } } } }</span>
由于该类中有findViewById的初始化操作,所以,在Activity的onCreate方法中必须调用上面的init()方法。如:
<span style="font-size:18px;">TitleManager tm = TitleManager.getInstance(); tm.init(this); tm.showUnloginTitle();</span>
界面切换
界面切换的核心方法是ViewGroup的addView和removeView方法。
首先为中间部分的界面写一个抽象的基类BaseUI,并在类中写获得需要在中间容器中加载的内容的方法。中间部分的界面都继承该基类。
/** * 所有界面的基类 * * @author HP1 * */ public abstract class BaseUI implements OnClickListener { protected Context context; /** * 显示在中间部分的布局 */ protected ViewGroup view; public BaseUI(Context context) { super(); this.context = context; init(); setListener(); } /** * 初始化布局 */ public abstract void init(); /** * 设置按钮的监听 */ public abstract void setListener(); /** * 默认的空白监听 */ @Override public void onClick(View v) { } /** * 获取需要在中间部分加载的内容 * @return */ public View getChild(){ // 设置layout参数 if(view.getLayoutParams() == null){ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1); view.setLayoutParams(params); } return view; } /** * 各界面的id(自定义的常量) * @return */ public abstract int getID(); }
中间显示内容例子:
之前在类中用View.inflate(context, resource, root);使布局文件转换成View对象时,都是设置root为null,这次设置为null时,显示效果有问题,产生原因是:
root为null时,view.getLayoutParams()为null,源码中布局参数为空时,没有设置view的宽高信息,所以这里需要我们自己设置view的宽高信息。
之前在Listview中设置root为null,却没有出现显示效果的问题,是因为Listview的源码中给自己的子孩子都设置了宽高信息。
/** * 购彩大厅 * * @author HP1 * */ public class Hall extends BaseUI implements OnClickListener { private TextView ssq_summary; private ImageView ssq_bet; public Hall(Context context) { super(context); init(); setListener(); } @Override public void init() { view = (LinearLayout) View.inflate(context, R.layout.il_hall1, null); ssq_summary = (TextView) view.findViewById(R.id.ii_hall_ssq_summary); ssq_bet = (ImageView) view.findViewById(R.id.ii_hall_ssq_bet); } @Override public void setListener() { ssq_summary.setOnClickListener(this); ssq_bet.setOnClickListener(this); } @Override public void onClick(View v) { super.onClick(v); } @Override public int getID() { return ConstantValue.HALL; } }
在中间部分管理者中写changeUI()的方法。在该方法中用removeView()(或removeAllViews())和addView()方法切换界面。
<span style="font-size:18px;">/** * 中间容器的管理者,继承了Observable,作为被观察者 * @author HP1 * */ public class MiddleManager extends Observable{ // 单例模式 private static MiddleManager instance = new MiddleManager(); public void MiddleManager(){} public static MiddleManager getInstance() { return instance; } private RelativeLayout ui_middle; public void setUi_middle(RelativeLayout ui_middle) { this.ui_middle = ui_middle; } public Context getContext(){ return ui_middle.getContext(); } /** * 用来存储创建过的界面。用手机内存,换应用的运行速度 * key是界面的简单名称,value是界面 */ private Map<String,BaseUI> VIEWCACHE = new HashMap<String,BaseUI>(); private BaseUI currentUI; /** * 用户操作的历史记录,类似于任务栈 */ private LinkedList<String> HISTORY = new LinkedList<String>(); /** * 切换界面的核心方法 * @param targetClazz 参数是目标界面的字节码,可以避免每次切换界面时都创建一个目标界面 */ public void changeUI(Class<? extends BaseUI> targetClazz) { // 判断当前界面和目标界面是否为同一个界面,若为同一个界面,直接return if(currentUI != null && currentUI.getClass() == targetClazz){ return; } BaseUI targetUI = null; String key = targetClazz.getSimpleName(); // 判断目标界面是否已经创建过--已经创建过的界面需要用map存储起来 if(VIEWCACHE.containsKey(key)){ // 若已经创建过,则重用 targetUI = VIEWCACHE.get(key); }else{ try { // 没有创建过,则创建 // 根据界面的字节码获得有参的构造器 Constructor<? extends BaseUI> constructor = targetClazz.getConstructor(Context.class); targetUI = constructor.newInstance(getContext()); VIEWCACHE.put(key, targetUI); } catch (Exception e) { // 由于下面代码要用到targetUI,若出异常会崩溃,所以,这里需要抛出异常。 throw new RuntimeException("构造器创建目标界面实例时出错!"); } } ui_middle.removeAllViews(); View child = targetUI.getChild(); ui_middle.addView(child); currentUI = targetUI; // 将当前显示的界面放到栈顶 HISTORY.addFirst(key); // 执行切换动画 Animation animation = AnimationUtils.loadAnimation(getContext(),R.anim.ua_view_change); child.startAnimation(animation); // 当中间容器切换成功时,通知另外两个容器变化 notifyTitleAndBottom(); } /** * 三个容器联动 * 通知所有的观察者,被观察者切换到了id为currentUI.getID()的界面 */ private void notifyTitleAndBottom() { setChanged(); notifyObservers(currentUI.getID()); } public boolean goBack() { if(HISTORY.size() > 1){ // 移除栈顶元素 HISTORY.removeFirst(); if(HISTORY.size() > 0){ // 得到新的栈顶元素 String key = HISTORY.getFirst(); // 获得对应栈顶元素的界面并展示 BaseUI targetUI = VIEWCACHE.get(key); ui_middle.removeAllViews(); View child = targetUI.getChild(); ui_middle.addView(child); currentUI = targetUI; notifyTitleAndBottom(); return true; } } return false; } }</span>
然后在Activity中findViewById找到中间部分占着位置的相对布局,并把该布局传递给管理者。
<span style="font-size:18px;">ui_middle = (RelativeLayout) findViewById(R.id.ui_middle); MiddleManager.getInstance().setUi_middle(ui_middle);</span>
观察者设计模式
①被观察者继承Observable,观察者实现Observer接口。
②Activity初始化时建立观察者和被观察者之间的关系。
<span style="font-size:18px;">MiddleManager.getInstance().addObserver(TitleManager.getInstance()); MiddleManager.getInstance().addObserver(BottomManager.getInstrance());</span>
③当观察者变化时通知被观察者。被观察者做出相应的响应。
相关文章推荐
- 【Unity技巧】统一管理回调函数——观察者模式
- 【Unity技巧】统一管理回调函数——观察者模式
- [界面设计模式]_[观察者模式]
- 【Unity】中如何统一管理回调函数(利用观察者模式)
- 【Unity技巧】统一管理回调函数——观察者模式
- 探究观察者设计模式
- 用 spring 实现观察者设计模式
- 统一界面设计
- 统一界面设计
- .NET中的设计模式五:观察者模式 选择自 lane_cn 的 Blog
- C#中利用代理实现观察者设计模式
- .NET中的设计模式五:观察者模式
- 设计模式理解 - 伟大的【Observer 观察者模式】
- 认识观察者模式(设计模式)[转载]
- 软件项目管理系统(RPMS)界面设计列表
- 统一界面设计
- 设计模式之观察者模式
- 设计模式PHP5实现之----观察者(Observer)
- IssueVision 学习笔记(三)-----设计模式之OBSERVER(观察者)模式
- 设计模式——观察者模式