您的位置:首页 > 移动开发

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,实现其效果。在这里献丑了,希望大神前来指导纠正。
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: