Android Action Bar

轉自: http://www.apkbus.com/forum.php?mod=viewthread&tid=69132


Action BarANDROID應用用到的重要開發資源之一,Action Bar提供了一致的應用導航和視圖切換方式,也提供了突出的和容易的以可預見的方式執行重要操作的方式。         Action Bar一般位於屏幕頂部,包括四個可操作區域:應用圖標或LOGO區域,用於視圖控制的Spinner下拉菜單TAB控件區域,Action button(也稱爲Action Item區域,提供溢出菜單的Action overflow區域。

      另外Action Bar還提供與上下文選中項相關的Contextual Action Bar、以及與菜單項綁定的Action View以及提供共享服務的Share Action Provider
      從功能上整個系統類圖分成相對對立的三個部分,一是視圖控制部分、二是Action Provider部分、三是菜單呈現部分。
                             
                                                         圖1    ActionBar視圖控制部分
       圖1爲ActionBar視圖控制部分類圖。Action Bar包括幾個顯示區域,每個區域分別由不同的視圖類型來顯示,每個視圖類型對應圖1類圖中的不同的視圖對象。
       應用圖標對象所在視圖對應ActionBarView對象的HomeView類型的內部視圖對象mHomeLayout,ActionBarView的OnClickListener類型的回調對象mUpClickListener提供對應用圖標操作的動作監聽,從而通過回調傳給實際ACTIVITY的onMenuItemSelected回調函數,在onMenuItemSelected回調函數中進行相應動作處理。
       用於視圖控制的Spinner下拉菜單對應ActionBarView中的Spinner對象mSpinner(通過創建一個SpinnerAdapter對象爲其提供下拉菜單項),ActionBarView的AdapterView.OnItemSelectedListener類型的mNavItemSelectedListener是其事件的監聽對象,當選中SpinnerAdapter對象的下拉項時觸發事件,使mNavItemSelectedListener對象的onItemSelected回調函數被調用,onItemSelected中調用ActionBar.OnNavigationListener類型 的應用對象的onNavigationItemSelected函數進行相應事件處理。ActionBar.OnNavigationListener對象連同SpinnerAdapter對象都是通過ActionBarImpl對象的setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback)函數傳給ActionBarView對象的。爲了打開下拉菜單功能還需要調用ActionBarImpl對象setNavigationMode函數設置NavigationMode爲ActionBar.NAVIGATION_MODE_LIST模式。
       Action Button對象所在視圖對應AbsActionBarView對象的ActionMenuView類型的內部對象mMenuView。每個Action Button實際對應一個菜單項,可以採用菜單項一樣的方式進行處理,在具體ACTIVITY 的onCreateOptionsMenu()回調中進行菜單資源的讀取和安裝,菜單資源通過XML資源文件進行的定義。由菜單資源XML文件中的android:showAsAction屬性定義一個菜單項爲Action Button。  Action Button的呈現由ActionMenuPresenter對象負責。
       溢出菜單和Action Button的子菜單也是在菜單資源XML文件中進行定義,當在菜單XML資源文件中定義Action Button的android:showAsAction屬性定義爲"ifRoom"時,當活動條沒有足夠空間時Action Button顯示到溢出菜單所在空間。溢出菜單的呈現由派生自MenuPopupHelper對象的OverflowPopup負責,Action Button的子菜單由派生自MenuPopupHelper對象的ActionButtonSubmenu負責呈現。
       Contextual Action Bar對應ActionBarContextView類,ActionBarContextView視圖由ActionBarImpl對象的startActionMode函數通過調用其initForMode函數進行初始化(以ActionModeImpl對象作爲參數 ) ,ActionBarContextView視圖的菜單採用ActionModeImpl對象的菜單,ActionModeImpl對象的菜單的生成及菜單項的事件處理都通過ActionModeImpl對象的ActionMode.Callback類型的回調對象處理,ActionBarContextView菜單的呈現也是由ActionBarContextView對象創建的相應的ActionMenuPresenter對象負責
         ActionMode.Callback類型的回調對象通過startActionMode函數的參數傳給ActionModeImpl對象,ActionMode.Callback類型的回調對象是用戶爲特定上下文視圖定義的。因此用戶爲了使特定視圖有上下文Action Bar,需要如下兩部工作:
        1 實現ActionMode.Callback回調接口,在ActionMode.Callback回調函數中生成相應菜單及完成菜單項的事件處理代碼。
        2 調用startActionMode(ActionMode.Callback callback)來顯示上下文Action Bar。
        Action View對象對應ActionBarView對象中的mExpandedActionView,由ExpandedActionViewMenuPresenter對象負責呈現,每個Action View對象與菜單項進行綁定,在菜單資源XML文件中進行描述,由XML文件中的android:actionLayout及android:actionViewClass 屬性確定。
      TAB 控件組對應對象ActionBarImpl中的TabImpl對象組,在ScrollingTabContainerView視圖中顯示,爲了打開TAB導航模式,需要調用ActionBarImpl對象setNavigationMode函數設置NavigationMode爲ActionBar.NAVIGATION_MODE_TABS。TabImpl對象、ActionBarImpl對象、ScrollingTabContainerView視圖三者構成MVC模式關係,TabImpl對象對應Model, ActionBarImpl對象對於控制器,ScrollingTabContainerView對應視圖 。
      類圖中的 ActionBarImpl提供對各個視圖的控制功能。
    Action Provider元素機制與Action View差不多,和Action View一樣需要與菜單項綁定,也是在菜單資源的XML文件中爲菜單項指定綁定的Action Provider對象 ,由XML文件中的android:actionProviderClass屬性確定,只是Action Provider更復雜,包括更多的對象,而Action View只對應一個視圖對象。用戶在使用Action Provider時,需要創建派生自ActionProvider的具體ActionProvider類,並酌情實現ActionProvider的相應回調接口,尤其在具體ActionProvider類的onCreateActionView回調函數中需要創建相應的視圖,具體ActionProvider類可以具有獨立的佈局XML文件,在onCreateActionView回調中進行讀取來生成相應視圖。
                       
                                                2 ActionBar菜單呈現部分
     圖Action Bar相關視圖對象的菜單呈現及菜單構建相關類圖。
     Action Bar相關視圖的菜單呈現及菜單構建類圖包括負責菜單構建過程的菜單構建對象(MenuBuilder)、負責菜單容器及菜單項的視圖創建的菜單呈現對象(MenuPresenter)、菜單容器和菜單項視圖對象(view)三類對象構成,三類對象構成MVP模式。
         MenuBuilder對應MVP模式的modelMenuPresenter對應MVP模式的Presenter,視圖對象對應ViewMenuBuilder構建菜單的每一菜單項。MenuPresenterMenuBuilder對象讀取菜單項並生成相應的菜單項子視圖,創建的菜單項子視圖被添加到菜單容器視圖中,MenuPresenter也提供對MenuBuilder對象及其菜單項的獲取及其它操作。視圖通過MenuPresenter獲得和操作菜單和菜單項對應的視圖,在MVP模式中視圖和模式不直接交互。
       ActionBar系統包括四個MenuPresenter具體類,ActionMenuPresenter負責Action  Button及Contextual Action Bar對應的菜單視圖呈現,ExpandedActionViewMenuPresenter負責與菜單項綁定的Action View對象的視圖呈現,OverflowPopup負責溢出菜單對應的視圖呈現,ActionButtonSubmenu負責子菜單對應的視圖呈現。OverflowPopup和ActionButtonSubmenu都派生自MenuPopupHelper,由於OverflowPopup呈現的菜單爲MenuBuilder對象,ActionButtonSubmenu呈現的菜單對應SubMenuBuilder對象,因此MenuPopupHelper採用的MenuBuilder對象是一個適配器對象,採用了適配器模式對不同對象封裝成相同的接口。
       圖2 類圖中MenuItemImpl類是對應菜單項的具體實現類。MenuBuilder對象創建的每一個MenuItemImpl類型的菜單項放在MenuBuilder對象的的數組中。
       MenuPopupHelper對象也登記爲anchor視圖的監聽器,通過ViewTreeObserver對象來檢測菜單所在anchor視圖的變化。對於溢出菜單的anchor視圖爲OverflowMenuButton。
                
                                    3  action provider提供部分
        圖是系統提供的ShareActionProvider類及相關對象,提供快速存取提供共享服務的Action
        整個類圖主要包括ShareActionProviderActivityChooserModelActivityChooserViewActivityChooserViewAdapter等對象。
        派生自ActionProvider的具體類ShareActionProvider,用來實例化ActivityChooserModelActivityChooserView對象,併爲ActivityChooserView對象設置數據模式,生成視圖,操作和獲取Model信息,根據Model信息創建活動菜單。
           ActivityChooserModelActivityChooserViewActivityChooserViewAdapter三者構成MVC模式,分別對應ModelView及採用Adapter模式的ControlActivityChooserView通過ActivityChooserViewAdapter獲取ActivityChooserModel中的活動信息,ActivityChooserModel本身派生自DataSetObservable,可以在ActivityChooserView對象中爲ActivityChooserModel對象登記一個DataSetObserver類型的對象,ActivityChooserModel對象通過該對象向ActivityChooserView對象發送ActivityChooserModel對象中的數據變化通知。
            ActivityChooserModel對於通過intent從包管理器中獲得的符合intent條件的活動記錄(以ActivityResolveInfo類型保存在數組列表中mActivites)的排序方法採用了策略模式,排序方法被封裝成對象,在沒有通過setActivitySorter方法設置排序方法時,採用默認排序方法,由DefaultSorter對象封裝。DefaultSorter對象提供的排序方法是依據活動記錄中的weight值進行排序,被排序的活動記錄的weight值還依據記錄在HistoricalRecordHistoricalRecord中的活動通過讀私有的XML類型的共享歷史文件獲得)列表中的活動順序進行修改,依據HistoricalRecord列表的從後往前的順序爲mActivites數組中對應的對象增加weight值,活動歷史記錄中越往後的記錄在mActivites列表中對應活動增加的權值越小,最新的相應記錄增加的權值越大。

           HistoryPersister線程對象用於把HistoricalRecord列表中的記錄保存到歷史文件中。HistoryLoader線程對象用於讀取歷史文件到HistoricalRecord列表中。DataModelPackageMonitor對象用於監視數據包,在數據包更新時同步活動記錄列表mActivitesActivityChooserMode對象還通過Map類型的HashMap保證一個相同的歷史文件只能實例化一個ActivityChooserModel對象,是單例模式的具體應用。




以下轉自:http://blog.csdn.net/qinjuning/article/details/41984281

Android3.0 以後 Menu相關做了較大改變。ActionBar作爲新的Menu形式粉墨登場了。
3.0之後常見的Menu或ActionBar有這四種:
   圖1:普通的ContextMenu        
   圖2: ActionBar                                                

    圖3: ActionMode(Contxt-ActionBar)                圖4 屏幕下方的ActionBar-代碼裏稱之爲splitActionBar

                                           


ContextMenu, 爲某個View registerContextMenu後,顯示效果如圖一。                 

  調用流程爲: 長按 ->showContextMenu -> DecorView:: showContextMenuForChild() , 此時會創建一個ContextMenuBuilder   ,對應show一個MenuDialogHelper類,該類主要已listPopup的展示所有menuItem —> ContextMenuBuilder::show() ,調用createContextMenu創建ContextMenu項 —>View::createContextMenu() -> Activity::onCreateContextMenu()創建MenuItem()。

至此,ContextMenu的創建流程走完了。

   注意: 有些控件例如ListView等,會特殊處理長按事件的默認操作,即採用ActionMode模式,而不是ContextMenu菜單。例如:AbsListView中performLongPress()中會判斷是否設置了CHOICE_MODE_MULTIPLE_MODAL標記,如果設置了,即調用startActionMode 轉換爲ActionMode模式。


ActionBar初始化過程,

  回到PhoneWindow::installDecorView中。3.0之後的默認佈局就是:screen_action_bar.xml , 對應佈局如下:
screen_action_bar.xml 
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:fitsSystemWindows="true"  
  3.     android:orientation="vertical" >  
  4.   
  5.     <com.android.internal.widget.ActionBarContainer  
  6.         android:id="@+id/action_bar_container"  
  7.         style="?android:attr/actionBarStyle"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content" >  
  10.   
  11.         <com.android.internal.widget.ActionBarView  
  12.             android:id="@+id/action_bar"  
  13.             style="?android:attr/actionBarStyle"  
  14.             android:layout_width="match_parent"  
  15.             android:layout_height="wrap_content" />  
  16.   
  17.         <com.android.internal.widget.ActionBarContextView  
  18.             android:id="@+id/action_context_bar"  
  19.             style="?android:attr/actionModeStyle"  
  20.             android:layout_width="match_parent"  
  21.             android:layout_height="wrap_content"  
  22.             android:visibility="gone" />  
  23.     </com.android.internal.widget.ActionBarContainer>  
  24.   
  25.     <FrameLayout  
  26.         android:id="@android:id/content"  
  27.         android:layout_width="match_parent"  
  28.         android:layout_height="0dip"  
  29.         android:layout_weight="1"  
  30.         android:foreground="?android:attr/windowContentOverlay"  
  31.         android:foregroundGravity="fill_horizontal|top" />  
  32.   
  33.     <com.android.internal.widget.ActionBarContainer  
  34.         android:id="@+id/split_action_bar"  
  35.         style="?android:attr/actionBarSplitStyle"  
  36.         android:layout_width="match_parent"  
  37.         android:layout_height="wrap_content"  
  38.         android:gravity="center"  
  39.         android:visibility="gone" />  
  40.   
  41. </LinearLayout>  



   會初始化以下幾個自定義View:

             ActionBarContainer : FrameLayout,管理下面的ActionBarView 和 ActionBarContextView ,只會visible一個View。
             
              ActionBarView (對應圖2):: com.android.internal.widget.ActionBarView  用於顯示各種Menu的ViewGroup
               
              ActionBarContextView (對應圖3) :默認Gone, 這個自定義ViewGroup用來顯示ActionMode下的Menu
               
              ActionBarContainer -- splitActionBar (對應圖4): 默認Gone, 當Menu過多時,可以將菜單放到該視圖上。
                              判斷是否需要顯示splitActionBar是在PhoneWindow::installDecor創建的。即  
                                       android:uiOptions="splitActionBarWhenNarrow",默認是true.如果設置了,Menu將顯示在該View上。

顯示ActionBar的過程如下:

 installDecor@PhoneWindowjaa   

 
  1. // Post the panel invalidate for later; avoid application onCreateOptionsMenu  
  2. // being called in the middle of onCreate or similar.  
  3. mDecor.post(new Runnable() {  
  4.    public void run() {  
  5.       // Invalidate if the panel menu hasn't been created before this.  
  6.       PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);  
  7.       if (!isDestroyed() && (st == null || st.menu == null)) {  
  8.            invalidatePanelMenu(FEATURE_ACTION_BAR);  
  9.       }  
  10.    }  
  11. });      
   
此時會獲取Activity對應的   PanelFeatureState 對象。

 —>  PhoneWindow::preparePanel(PanelFeatureState st, KeyEvent event) 
 —> PhoneWindow::initializePanelMenu(st) ,會創建一個MenuBuilder對象,以後所有Menu就歸他管理了,爲ActionBar setMenu。
 —> cb.onCreatePanelMenu(st.featureId, st.menu), 默認就是Activity的方法了。
 —> Activity::onCreatePanelMenu , 創建MenuItem
 —> cb.onPreparePanel(),默認就是Activity的方法了, onPrepare。

支持ActionBar對應的MenuBuilder也全部初始化OK了。

ActionBarView 管理了以下幾種佈局:
        HomeLayout -- 顯示左側的應用程序圖標,回退箭頭等;

        TitleLayout      -- 如果存在titile,subtile則顯示
        不同模式下的視圖:
                STANDARD : ActionMenuView
                MODE_LIST:  adapter mSpinner, 通過代碼setDropdownAdapter設置適配器
                MODE_TAB :  tab   ScrollingTabContainerView ,管理所有TabView, ScrollingTabContainerView.TabView, 其選中背景圖由selected熟悉控制.

       MODE_LIST 和 MODE_TAB對應的視圖只能add 其中1個。

        ExpandView -- 如果某個Menu設置了 android:actionViewClass,即能expand collapse。
                如果展開時,其他視圖置爲GONE狀態,只顯示HomeLayout和該ExpandView。

ActionBarView 得自動實現measure和layout操作。


 ActionBarContainer -- splitActionBar  單純管理一個 ActionMenuView。

 ActionBarContextView 即處於ActionMode模式下的視圖管理
 
      自動在最左側添加一個√的CloseButton。
      可以設置TitleLayout或者自定義的CustomView
      管理一個 ActionMenuView。 initForMode方法時會初始化1個ActionMenuPresenter,提供該視圖。
     
             
ActionMenuView 核心主角登場,掌聲鼓勵。
 
         功能:管理MenuItem的視圖容器。每個Menu作爲一個cell,如果在屏幕上顯示不全,則會自動創建一個更多的View。

         measure 或layout時,計算較爲複雜。每個cell有個最小寬度單位。

ActionMenuItemView: 對應於每個MenuItem的View。由ActionMenuView管理。

BaseMenuPresenter: 根據MenuBuiler爲每個MenuItem創建ActionMenuItemView 或自定義的 actionClass----由     android:actionViewClass 或者android:actionProvider提供。

   方法解析:
          initForMenu : Menu設置
          getMenuView: 獲得創建的ActionMenuView 視圖容器
          updateMenuView : 更新ActionMenuView 的子View
          getItemView : 爲每個MenuItem創建View對象
          addItemView : 將創建的View對象添加至ActionMenuView  視圖容器中。
          bindItemView: 綁定數據

  ActionMenuPresenter 繼承於BaseMenuPresenter ,其構造方法提供了兩個視圖,分別傳遞Action ViewGroup和 Action View對象,用於其父類初始話佈局對象。並且它重寫了getItemView方法, 如果MenuItem提供了actionView則用它,否則用系統定義好的。另外,如果某個MenuItem 爲expand或者collapse狀態,則MenuPresenter相關事件會回調,更改MenuItem VISBILE狀態。

 點擊回調事件流程:

    ActionMenuItemView::onClick() 
  —>ActionMenuView::invokeItem
  —> MenuBuilder::performItemAction 
 —> MenuItemImpl:: invoke()   
  —> MenuBuilder:: dispatchMenuItemSelected ,此時的Callback爲PhoneWindow對象。


如果爲ActionMode模式,
 
    startActionMode() ,轉換爲ActionMode模式。流程如下:

  PhoneWindow::    startActionMode() 

  —>  Activity :: onWindowStartingActionMode   

  —> ActionBarImpl:: startActionMode 轉換爲ActionMode模式,初始化1個ActionModeImpl對象(內部構造1個新的MenuBuilder,用來管理該模式下的Menu),同時ActionContextView Visbile, ActionBarView隱藏。
 
  —>  繼續調用 ActionBarImpl :: dispatchOnCreate() , 回調Activity的onCreateActionMode 生成MenuItem

ActionMode的回調如下:  ActionModeImpl:: onMenuItemSelected  繼續回調給 PhoneWindow相關方法

ActionBarView::expandItemActionView  打開某個MenuItem對應的actionView, 會設置mExpandedActionView 請求重繪視圖
ActionBarView::collapseItemActionView  摺疊某個MenuItem對應的actionView



ActionProvider

  提供actionViewClass 以及對應的操作。對應的View由onCreateActionView()返回。

 
  吐槽下:發現csdn的博客編輯器還沒有有道雲筆記讓人舒坦,悲了個催。

備註:Android 2.X使用ActionBar得使用ActionBarSherlock 和 v7 appcompat library 
 
       使用注意: ①、兩者皆不支持Float Button,即自動顯示更多的按鈕.
                         ②、ActionMode等當然不會有咯...
 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章