转自: 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.youkuaiyun.com/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);
- }
- }
- });