app只有一个activity的ui框架设计猜想
2013-11-10 11:07
423 查看
当有人要求你开发一个app只能用一个activity,并且用java布局,你是否石化了?反正我全身都湿了。老大说他有他这要的道理,等你入门就就明白了。好吧!人家的实力,经验摆着那里,就从了吧!还是开始慢慢琢磨吧! 一.从物理上看屏幕上界面是一个view ,view对应一个actiivity,,竟然一个app只有一个acitivity,,那么只有一个view了。对于界面的切换,从业务逻辑上可以看一张纸page A, 当需要切换界面的时候,就用另外一张纸page B掉当前page A即可(当前页面指针指向page b)。当然页面跳转,不排除会传递参数,activity跳转通过intent传递参数 ,这里就采用数据包裹类 bundle.业务视图如下:对于一个page,最起码进行页面布局layout,为方便起见,又封装一下layout,整体包含关系如下图:二.对于app而言,触控和案件事件处理很重要,采用以下原则,进行封装1. 对于引起界面切换事件 ,统一留给MainView处理进行,大致出现情况有:(1) 控件点击(不包括视图中返回按钮)(2) List列表的item 点击事件(3)返回键 (留在后面再说,返回按钮和返回键归为OnBack事件,也是个值得考虑的问题) 2. 凡是page内部的触控事件交给page自己处理 有种很常用的情况是,在一个page内进行contentView切换,类似tabhost那种切换效果。对于page,可以按照下图理解:三.由于一个app只有activity,但按返回时,返回到上一个page,好像是不太可能,因此要拦截返回键事件自己处理,再者,page跳转时,我们是采取page覆盖删除,而不是隐藏,不像有activityManager或者activity来帮我们管理,则需要自己来维持page返回的堆栈,这里也才模仿activityManger来管理,封装了一个PageManager来管理和维持这个堆栈。似乎忘记了,在界面返回时,界面最好跟跳转前状态一个样(要是activity间跳转,这些系统都帮我们做了),而则要自己去保存恢复,比如checkbox是否被选中,listview滚动到哪里等,则需要保存这些信息,这里照样还是用包裹数据类Boundle保存,为此封装了pageinfo类,包含类的完整类名和状态信息。采用完整的类名,为了方便我们使用反射机制,实例化page对象,提高了封装度,而不是if else造成代码庞大。四.在界面来回切换时,界面都是new page ,delete page,而数据不能这样,从本地存储中读取或者网络获取,必须把有必要的数据hold在内存中,否则的话,效率是相当低的,这就需要封装了一个全局数据类,竟然是全局的,就必须是单例模式,我们很容易想application,为更好的封装,还是把数据独立封装成appData,保存写业务实体信息的各种集合。见下图:五. 类数据树结构图 纠正下,mainview是继承 RelativeLayout.六.具体类接口设计 1.MainViewpublic class MainView extends KeyboardListenRelativeLayout (为监听软件是否弹出的relativeLayout){ private final static String TAG="MainView"; private Context mContext; private OnClickListener mListener; private BasePage mCurPage; private Handler mHandler; private PageManager mPageMagager; public void initView(){} //处理界面中 列表item(响应页面跳转的item事件)点击事件 public void doOnItemClick() { //关闭软键盘 closeSofyBord(); //记录当前page PageManager管理 //删除当前page String curPageName=mPageMagager.getCurPageInfo().getName(); if(!curPageName.equals(pageName))//防止同时点击多个item,引起的混乱 { //为了讲究通用性,这里最好采用反射机制,但是同别人讲,最好别经常使用,这里就用if else了 if(pageName.equals(ChatPage.class.getName())) { if (this.mPage != null) this.mPage.delView(); mPage=new ChatPage(mContext); PageInfo pageInfo=new PageInfo(ChatPage.class.getName(),null,false); mPageMagager.pushPage(pageInfo); mPage.setBundle(bundle); mPage.initPage(this, mListener); } } } //处理 界面返回按钮 和返回键 事件 public void doOnBack(){} public void doOnClick(View v){} //关闭软件盘 public void closeSofyBord(){} }2.BasePage设计public abstract class BasePage { protected BaseLayout mLayout; protected Context mContext; protected OnClickListener mListener; protected Bundle mBundle; protected MainView mView; public void setBundle(Bundle b){} public void setBundle(Bundle b){} //删除page public void delView(){} public abstract void initPage(MainView view,OnClickListener l); public abstract void doOnClick(View v); }3.BaseLayout设计public abstract class BaseLayout { protected Context mContext; protected MainView mView; protected OnClickListener mListener; protected LinearLayout mlLayout; protected Bundle mBundle; //用于界面切换承载数据的载体 protected Handler mHandler; public void setBundle(Bundle b){} public void setBundle(Bundle b){} public void delLayout(){} //抽象方法 public abstract void initLayout(MainView view,OnClickListener l,Bundle bundle); public abstract void onDraw(Canvas canvas);}4.BaseWindow类设计public abstract class BaseWindow { protected Context mContext; protected LinearLayout mLayout; protected MainView mView; protected OnClickListener mListener; public abstract void initWindow(MainView v,OnClickListener l); public abstract void doOnClick(View v); public abstract void onDraw(Canvas canvas);}5.BaseInfo类设计public abstract class BaseInfo{ protected String mName; protected Bundle mStates;//状态值集合存储 public void putState(String key,String value){} public void putState(String key,String[] values){} public void putState(String key,boolean value){} public void putState(String key,boolean[] values){} public void putState(String key,int value){} public void putState(String key,int[] values){} public void setName(String Name){} public String getName(){} public void setStates(Bundle bundle) {} public Bundle getStates(){ }}public class PageInfo extends BaseInfo{ private boolean mHasCenters;//是否存在多个Centerwindow交互 标志符 public boolean hasCenters();}6.PageManager类设计public class PageManager { private Stack<PageInfo> mPageStore;//保存各界面的状态信息 private static PageManager mInstance; public synchronized void pushPage(PageInfo pageInfo){} public synchronized void popPage(PageInfo pageInfo){} public synchronized PageInfo popPage(){} public synchronized PageInfo getCurPageInfo(){} public synchronized void popAllPageInfos(){} public boolean isEmpty(){} }接下来就是接口方法的实现咯。当我们要添加一个page 时,只需要关注new page,new layout,即可,是否觉得很方便了,当然这样的设计,为了更好的封装和维护,牺牲性能。在实现过程中会出现各种问题,比如1.有些页面软件盘弹出时,需要把布局网上顶 adjust,有页面需要覆盖 span,在平常的都是在activity申明中设置软键盘模式,但这里只有activity。尝试了下,首先也是必须的,在activity申明中设置软键盘模式(否则后面在page中修改软件盘模式没有效果),然后再page中设置模式。我也只是碰巧的,没去挖掘原因。2.有些时候我们需要动态改变layout的长宽,就如语音消息播放时,随着语音时间长度,语音消息的长度就会变化,而layout并没有没有提供setWidth和setHeight,但是可以通过getLayoutParams获取LayoutParams,来改变LayoutParams的静态属性 width和height,实现其效果。在这里献丑了,希望大神前来指导纠正。
相关文章推荐
- android基础篇一
- android学习笔记(2)-项目的目录结构与启动过程分析
- Intent七在属性之一:ComponentName 分类: H1_ANDROID 2013-11-10 10:54 1184人阅读 评论(1) 收藏
- 同一wifi下,android 模拟器(genymotion) 连接 PC成功 心得
- Android LogCat 日志记录
- Baidu Map 2.3.1获取Android签名证书
- Android的file文件操作详解
- Android SharedPreferences使用类
- IOS学习笔记57--IOS7状态栏适配(二)
- Android 博文目录
- IOS学习笔记56-IOS7状态栏适配方法 (一)
- Android JUnit单元测试
- Android四大(五大)基本组件简介
- 解决Android中,禁止ScrollView内的控件改变之后自动滚动
- 学习Android之内部类
- Android四大基本组件介绍与生命周期
- Android Service完全解析,关于服务你所需知道的一切(下)
- Android Service完全解析,关于服务你所需知道的一切(上)
- Android - 文件读写操作 总结
- Android横竖屏切换总结