action bar是一个标示用户位置的窗口功能,可以提供用户操作和导航模式。使用action bar可以为用户提供熟悉的界面(如果其他应用也使用action bar),系统可以为action bar优雅适配不同的屏幕配置。
图1. 一个action bar 包含:[1]应用图标,[2]两个操作项,[3]更多操作
action bar提供了一些关键功能:
l 提供一个标志指明用户在你的应用中的位置。
l 提供一个可见的方式来突出和访问重要的操作(如搜索)
l 支持应用内部一致的导航和视图切换(使用tabs或下拉列表方式)
ActionBar APIs第一次出现是在Android 3.0(API 11)中,但是可以使用支持库向下兼容到Android 2.1(API 7)。
这篇指导专注于怎样使用兼容库的action bar,如果你的应用只需要支持android3.0或更高版本,那么你应该使用framework中的ActionBar APIs。大部分的APIs是相同的,除了一些不同的包命名空间。
注意:要注意你应该从合适的包中引入ActionBar类:
u 如果支持API 11以下,使用:
import android.support.v7.app.ActionBar
u 如果仅支持API 11及以上,使用:
import android.app.ActionBar
增加Action Bar
像上面提到的,这个文章专注于怎么使用兼容库中的ActionBar.所以在增加ActionBar之前,你必须在你的工程中添加v7支持库。一旦你的工程添加好支持库之后,接下来就可以增加ActionBar了:
1.让你的Activity继承ActionBarActivity
2.为你的Activity使用(或继承)一个Theme.AppCompat主题,例如:
<activity android:theme="@style/Theme.AppCompat.Light" ... >
在API level 11或更高版本上,action bar已经默认被添加到所有的使用Theme.Holo主题的activity中,这是默认的主题当targetSdkVersion 或minSdkVersion 被设置为11或更高的时候。如果你的activity不需要使用action bar,那么对它使用主题Theme.Holo.NoActionBar。
移除Action Bar
你可以在运行时隐藏action bar,例如:
ActionBar actionBar = getSupportActionBar();actionBar.hide();
在API 11或更高版本上,使用getActionBar()来获取ActionBar 对像。
当action bar 被隐藏之后,系统会适配你的布局来填满此时可用的屏幕空间。你可以调用show()函数来重新显示action bar.
要注意隐藏或显示action bar会导致你的activity进行重量布局,因为要计算action bar消耗的空间。如果你的应用经常隐藏或显示action bar,你或许要考虑使能overlay模式。overlay模式将你的action bar画在你的activity前面,模糊了顶端。这种方式,你的布局在action bar显示或隐藏时保持固定。要使能overlay模式,为你的activity创建一个客户主题,在主题中设置windowActionBarOverlay 为true。
使用logo代替图标
默认情况下,系统在action bar中使用你的应用程序图标,图标在<application>节点或<activity>节点中指明。当然,你也可以使用logo属性来代替图标显示在action bar中。
logo通常比较图标宽,但是不要包含不需要的文字信息。你通常应该使用一个被用户认可代表你的品牌的logo。一个很好的例子是YouTube 的应用的logo----这个logo代表用户期望的品牌,而应用的图标是符合各种启动器的修改版本。
增加Action 项
图2. 有三个操作按钮和一个更多操作按钮的Action bar.
action bar根据应用当前上下文为用户提供最重要的操作项。那些直接使用图标或文字出现的是操作按钮。那些超出显示范围或不是特别重要的操作隐藏在更多操作按钮中。用户可以通过按下更多操作按钮来显示一列其它的操作项,或者通过设备的Menu键。
当你的activity启动后,系统通过调用你的activity的onCreateOptionsMenu()弹出操作项。使用这个方法来实例化一个定义了所有操作的菜单资源。例如,这里是一个定义了一对菜单项的菜单资源:
res/menu/main_activity_actions.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_search" android:icon="@drawable/ic_action_search" android:title="@string/action_search"/> <item android:id="@+id/action_compose" android:icon="@drawable/ic_action_compose" android:title="@string/action_compose" /></menu>
然后在你的activity的onCreateOptionsMenu()方法中实例化菜单资源,从而将每一个菜单项增加到action bar中:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
为了将一个操作项直接作为操作按钮显示在action bar上,需要在<item>标签中包含showAsAction="ifRoom". 例如:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
<item android:id="@+id/action_search" android:icon="@drawable/ic_action_search" android:title="@string/action_search" yourapp:showAsAction="ifRoom" />
...
</menu>
当然,如果在action bar上已经没有显示空间的话,它还是会显示到更多操作按钮的列表中去。
从支持库中使用XML属性
注意在上面<menu>标签中对showAsAction属性使用一个客户命名空间。这是必要的当使用任何支持库中定义的XML属性时,因为这些属性在老设备的安卓framework中不存在。所以在使用支持库定义的所有XML属性时,你必须使用你自己的命名空间。
如果你的菜单项同时提供标题和图标----使用title和icon属性---那么默认只显示图标。如果你还需要显示文字,那么在showAsAction属性中增加"withText",例如:
<item yourapp:showAsAction="ifRoom|withText" ... />
注意:值"withText"是文字应该出现在action bar的提示。action bar会显示文字只有在可能的情况下,如果定义了图标并且在考虑节省空间的时候那么就不会显示了。
你应该总是定义菜单项的title,甚至你并不打算让title出现在操作项中,基于以下几点考虑:
l 如果这里没有足够的空间来显示操作项,那么操作项会被放到更多操作列表中,并且在列表中只显示title
l 屏幕阅读器为弱视用户读取菜单项的title
l 如果操作项只显示了图标,用户可以长按这个图标来显示一个操作项的title.
图标是可选的,但是推荐使用它。图标设计建议,请参阅图标设计指南。你可以从下载页面下载一系列标准的action bar图标(例如搜索和丢弃)。你可以使用“always"来让操作项一直表现为操作按钮,但是通常情况下你应该使用"ifRoom",除非有特别的需求,比如操作项包含一个action view并且不能在非操作按钮时扩展。
处理操作按钮的点击
当用户按下一个操作,系统会调用你的activity的onOptionsItemSelected()方法。使用MenuItem作为参数传入到这个方法,你可以调用getItemId()来确定是哪一个操作被按下,getItemId()返回你在<item>中定义的id标签。例如:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_search:
openSearch();
return true;
case R.id.action_compose:
composeMessage();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
注意:如果你使用Fragment类的onCreateOptionsMenu()实例化菜单项,当操作被按下时那么系统会优先调用activity的onOptionsItemSelected(),然后再调用那个Fragment的onOptionsItemSelected(),当activity不打算处理此操作项时,为了确保fragment的onOptionsItemSelected()会被调用,activity需要对此操作项的点击返回super.onOptionsItemSelected(),而不是返回false。
使用分离的action bar
图3. 左边显示的是一个有tab的action bar,中间显示分离的action bar,右边显示分离的隐藏了应用标题和图标的action bar。
分离的action bar在屏幕的底部提供了一个独立的用于显示所有操作项栏,当activity运行在窄屏的时候(比如一个竖直方向的手持设备)。
通过分离的action bar这种方式,确保在一个窄屏上面为显示你的所有操作项提供合理的空间,将顶部空间留给导航和标题等元素。
为了在支持库的基础上使用分离action bar,你必须做两件事:
1. 在manifest文件中,为<application>节点或每个<activity>节点增加uiOptions="splitActionBarWhenNarrow",这个属性只被API 14或更高版本支持。
2. 为了支持旧的版本,在每个<activity>节点中增加子标签<meta-data>并定义"android.support.UI_OPTIONS"的值为"splitActionBarWhenNarrow"。
例如:
<manifest ...>
<activity uiOptions="splitActionBarWhenNarrow" ... > <meta-data android:name="android.support.UI_OPTIONS" android:value="splitActionBarWhenNarrow" />
</activity>
</manifest>
使用分离action bar也允许导航tab扩展到主action bar,如果你移除应用的图标和标题的话(像上面图3)。为了创建这种效果,需要禁用应用的图标和标题,使用函数setDisplayShowHomeEnabled(false) 和setDisplayShowTitleEnabled(false)。