轉自: http://www.apkbus.com/forum.php?mod=viewthread&tid=69132
Action Bar是ANDROID應用用到的重要開發資源之一,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菜單呈現部分
圖2 是Action Bar相關視圖對象的菜單呈現及菜單構建相關類圖。
Action Bar相關視圖的菜單呈現及菜單構建類圖包括負責菜單構建過程的菜單構建對象(MenuBuilder)、負責菜單容器及菜單項的視圖創建的菜單呈現對象(MenuPresenter)、菜單容器和菜單項視圖對象(view)三類對象構成,三類對象構成MVP模式。
MenuBuilder對應MVP模式的model,MenuPresenter對應MVP模式的Presenter,視圖對象對應View。MenuBuilder構建菜單的每一菜單項。MenuPresenter從MenuBuilder對象讀取菜單項並生成相應的菜單項子視圖,創建的菜單項子視圖被添加到菜單容器視圖中,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提供部分
圖3 是系統提供的ShareActionProvider類及相關對象,提供快速存取提供共享服務的Action。
整個類圖主要包括ShareActionProvider、ActivityChooserModel、ActivityChooserView、ActivityChooserViewAdapter等對象。
派生自ActionProvider的具體類ShareActionProvider,用來實例化ActivityChooserModel、ActivityChooserView對象,併爲ActivityChooserView對象設置數據模式,生成視圖,操作和獲取Model信息,根據Model信息創建活動菜單。
ActivityChooserModel、ActivityChooserView、ActivityChooserViewAdapter三者構成MVC模式,分別對應Model、View及採用Adapter模式的Control,ActivityChooserView通過ActivityChooserViewAdapter獲取ActivityChooserModel中的活動信息,ActivityChooserModel本身派生自DataSetObservable,可以在ActivityChooserView對象中爲ActivityChooserModel對象登記一個DataSetObserver類型的對象,ActivityChooserModel對象通過該對象向ActivityChooserView對象發送ActivityChooserModel對象中的數據變化通知。
ActivityChooserModel對於通過intent從包管理器中獲得的符合intent條件的活動記錄(以ActivityResolveInfo類型保存在數組列表中mActivites)的排序方法採用了策略模式,排序方法被封裝成對象,在沒有通過setActivitySorter方法設置排序方法時,採用默認排序方法,由DefaultSorter對象封裝。DefaultSorter對象提供的排序方法是依據活動記錄中的weight值進行排序,被排序的活動記錄的weight值還依據記錄在HistoricalRecord(HistoricalRecord中的活動通過讀私有的XML類型的共享歷史文件獲得)列表中的活動順序進行修改,依據HistoricalRecord列表的從後往前的順序爲mActivites數組中對應的對象增加weight值,活動歷史記錄中越往後的記錄在mActivites列表中對應活動增加的權值越小,最新的相應記錄增加的權值越大。
HistoryPersister線程對象用於把HistoricalRecord列表中的記錄保存到歷史文件中。HistoryLoader線程對象用於讀取歷史文件到HistoricalRecord列表中。DataModelPackageMonitor對象用於監視數據包,在數據包更新時同步活動記錄列表mActivites。ActivityChooserMode對象還通過Map類型的HashMap保證一個相同的歷史文件只能實例化一個ActivityChooserModel對象,是單例模式的具體應用。
以下轉自:http://blog.csdn.net/qinjuning/article/details/41984281
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:fitsSystemWindows="true"
- android:orientation="vertical" >
- <com.android.internal.widget.ActionBarContainer
- android:id="@+id/action_bar_container"
- style="?android:attr/actionBarStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
- <com.android.internal.widget.ActionBarView
- android:id="@+id/action_bar"
- style="?android:attr/actionBarStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- <com.android.internal.widget.ActionBarContextView
- android:id="@+id/action_context_bar"
- style="?android:attr/actionModeStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone" />
- </com.android.internal.widget.ActionBarContainer>
- <FrameLayout
- android:id="@android:id/content"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:foreground="?android:attr/windowContentOverlay"
- android:foregroundGravity="fill_horizontal|top" />
- <com.android.internal.widget.ActionBarContainer
- android:id="@+id/split_action_bar"
- style="?android:attr/actionBarSplitStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:visibility="gone" />
- </LinearLayout>
- // Post the panel invalidate for later; avoid application onCreateOptionsMenu
- // being called in the middle of onCreate or similar.
- mDecor.post(new Runnable() {
- public void run() {
- // Invalidate if the panel menu hasn't been created before this.
- PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (!isDestroyed() && (st == null || st.menu == null)) {
- invalidatePanelMenu(FEATURE_ACTION_BAR);
- }
- }
- });