TabActivity,LocalActivityManager,TabHost,TabWidget深度分析

TabAcitivity继承自AcitivtyGroup,AcitivityGroup的主要作用是创建一个LocalActivityManger,然后把activity的onCreate等事件传递给LocalActivity来处理,作用仅此而已,非常简单。

TabActivity真正重要的包括三部分,TabHost,TabWidget,LocalActivityManager.

TabHost主要是面向用户的接口,它的主要作用就是添加tab,用TabSpec来完成一个完整的tab的抽象(包括标签及其内容),一个string 类型的tag,这个tag用来标识一个tab,比如在退出程序时记录当前是哪个tab以便在再次进入的时候显示退出前显示的tab,它最重要的作用在于当用intent做为一个tab,即要把一个activity作为内容(content)嵌入(即embeded activity的概念)进去,成为一个tab的内容。

另外一个在TabHost中比较重要的部分就是,它主要运用了策略模式来完成标签和内容的抽象。

创建一个接口IndicatorStrategy,用一个方法createIndicatorView()来创建view(即在TabWidget上显示的标签),根据传入的参数不同,有LabelIndicatorStrategy,LabelAndIconIndicatorStrategy,ViewIndicatorStrategy三种。从名称即可以看出标签可以为一个只含有String,也可以含有String和一张图片,或者用户自定义的view等三种形式。

用接口ContentStrategy来抽象内容,有两个方法,getContentView()用来获取view,用tabClosed()来完成关闭的操作(比如用户点击其他tab,关闭当前的tab),按照内容的不同有ViewIdContentStrategy(给定一个layout id作为内容),FactoryContentStrategy(用户实现继承TabContentFactory,用createTabContent()来创建一个view作为内容),IntentContentStrategy(指定一个intent(即将一个activity作为内容))三种方式。内容的rootView是一个framelayout,切换是通过让选择的内容visible,让原来的view invisible实现的。在刚开始点击标签时创建view,在后面的时候直接用。所以将actvity作为内容时,如果创建需要很长时间的话可能会觉得迟钝(这里可能可以通过在创建tabhost的时候首先完成费时的操作这一办法减少迟钝感),而再后面切换的时候感觉很顺畅。

其中把activity内容是通过用LocalActvityManager来启动activity,并获取到一个window,再获取window的decorView来得到view,然后作为内容。代码如下:

final Window w = mLocalActivityManager.startActivity( mTag, mIntent);

             final View wd = w != null ? w.getDecorView() : null;


上节分析了TabHost,这节接着分析TabWidget.

TabWidget比较简单,它继承自LinearLayout,用来放标签。它覆盖了addView(View child)来实现添加一个标签。在没有指定view的LayoutParams时它默认给标签加上高度充满TabWidget,宽度上根据标签个数平分的LayoutParams,这样,如果在添加标签时没有设定LayoutParams的时候就会看到标签平均分布的情况。然后再根据有没有dividerDrawable来判断是否添加,这个dividerDrawable应该是标签之间的那个图片。TabWidget规定的较固定,使用起来的时候有可能很不美观,实际上看到网上有人说用TabActivity还不如用Gallery,这句话有一定道理,如果不需要把一个activity作为一个view嵌入进去的话使用Gallery的确更美观更炫,但存在就有道理,我想TabActivity真正存在的原因就是为了embeded activity,即把activity做为一个view加入到另一个actvity中,而又有LocalActivityManger来控制activity的生命周期所以不必操心生命周期问题。由于TabWidget的布局较为固定,所以可能会导致看起来不美观,有需要根据需求定制自己的TabWidget的需要(比如我自己就在TabWidget中间加入空隙,使它看起来有标签被分组了的效果),在修改的时候需要注意两个函数:getChildTabViewAt(int index)和getTabCount(),由于系统本身的view排布要么全部是标签,要么一个dividerDrawable加一个标签的排布,所以这两个函数实现较为简单,如果定制自己的TabWidget的话可能需要修改这两个函数,会稍微复杂点。

LocalActivityManager的话主要看一个函数startActivity(String id, Intent intent),因为String型的id是用来标识一个activity的,所以在addTab()的时候不能让tab tag重。因为TabActivity中当点击内容是activity的标签时就会调用startActivity()来获取view,而在启动的时候根据Intent的Flags处理有所不同,所以设置IntentFlags的时候需要注意,(以下此段来自个人翻译,英语水平差如又错误请见谅)如果在调用startActivty()的时候这个id 下已经有一个activity被启动了的话,那么根据不同情况它要么被destroy然后再重新创建一个然后启动,要么就直接使用它。原文和翻译如下:

/**

     * Start a new activity running in the group.  Every activity you start

     * must have a unique string ID associated with it -- this is used to keep

     * track of the activity, so that if you later call startActivity() again

     * on it the same activity object will be retained.

     * 

     *启动一个运行在group的新的activity.每一个启动的actvity必须拥有

     *一个唯一的string ID,它被用来记录activity的踪迹,所以如果下次

     *再次调用startActivity() 的时候,相同的activity 对象将被保留下来。

     *

     * <p>When there had previously been an activity started under this id,

     * it may either be destroyed and a new one started, or the current

     * one re-used, based on these conditions, in order:</p>

     * 

     *如果在这个id下已经有一个activity启动了的话,那根据不同情况

     *它要么被destroyed掉然后启动一个新的,要么当前存在的这个

     *被重新使用,按以下顺序:

     * <ul>

     * <li> If the Intent maps to a different activity component than is

     * currently running, the current activity is finished and a new one

     * started.

     * 

     *如果intent映射到跟当前运行的不同的 activity commponent(包名)

     *的话,当前的activity会被结束掉然后一个新的会被启动。

     *

     * <li> If the current activity uses a non-multiple launch mode (such

     * as singleTop), or the Intent has the

     * {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} flag set, then the current

     * activity will remain running and its

     * {@link Activity#onNewIntent(Intent) Activity.onNewIntent()} method

     * called.

     *

     * 如果当前的activity用了不是多运行的模式(比如 singleTop),

     * 或者intent 设置了 FLAG_ACTIVITY_SINGLE_TOP,那么当前的activity

     * 仍旧会继续运行并且会调用 Activity.onNewIntent().

     *

     * <li> If the new Intent is the same (excluding extras) as the previous

     * one, and the new Intent does not have the

     * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} set, then the current activity

     * will remain running as-is.

     * <li> Otherwise, the current activity will be finished and a new

     * one started.

     * </ul>

     * 

     * 如果新的intent(不包括 extras)和以前的完全一样,并且没有设置

     * FLAG_ACTIVITY_CLEAR_TOP ,那么当前的 actvity 仍然会继续运行。

     *否则(其他情况下),当前的activity会被结束掉然后启动一个新的activity。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值