TabActivity,LocalActivityManager,TabHost,TabWidget深度分析

來源:互聯網
上載者:User

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。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.