ActionBar是一种标识了用户的当前位置,并且提供用户行为及导航模式的窗口功能。由于系统对于ActionBar在不同屏幕大小下都做了很好的支持,所以使用ActionBar可以给用户提供一个统一的体验。
如上图所示,ActionBar提供了一些主要功能:
【1】将一些重要的行为动作(如:搜索)放在一个显而易见的位置上。
【2】支持统一的导航模式和视图的切换。
【3】通过给那些较少使用的行为动作提供一个行为溢出器(action overflow)减少行为干扰。
【4】提供了一个专门的区域,用来标识我们的APP
如上图所示,ActionBar一般分为4个功能区域:
1.App icon(应用图标区域)
应用图标是我们应用的一个标识。注意:如果用户当前不是处于最上层的页面(如首页),那么我们就需要展示最左侧的导航箭头,以便用户能返回到上一级页面。
2.View control(视图控制区域)
如果你的app在不同的视图中展示数据(比如,通过筛选状态展示数据),这个区域就是用来让用户切换视图的。如果你的app没有这个需求,那么这部分可以展示一个非交互的内容,比如一个页面标题等。
3.Action buttons(动作按钮)
显示一些最重要的动作按钮。其它一些不适合放在ActionBar上的动作都被放置到行为溢出器(action overflow)中。长按显示动作的名字。
4.行为溢出器(action overflow)
将那些不常用的动作行为都放置到这个溢出器内。
ActionBar是在Android 3.0(API level 11)时被添加的,但是Android 2.1(API level 7)及以上版本也可以通过Support Library支持包去使用。这里我们主要去学习低版本中的ActionBar,而API level 11以上的版本只是引用包的不同而已,如果App的最低版本低于Api level 11,需要使用import android.support.v7.app.ActionBar。如果App最低版本为11或者以上,则可以直接使用import android.app.ActionBar。
1. 添加ActionBar
在上面我们有提到,这次我们学习的是Support Library支持包中的ActionBar,所以在我们学习添加一个ActionBar之前,我们需要给我们的App建立appcompat v7支持包。(Android Studio会帮我们默认引用,Eclipse则需要自己去设置,设置方式点击这里)
当你建立好appcompat v7支持包后,就可以开始添加ActionBar了:
【1】创建我们的Activity,并且继承自ActionBarActivity
【2】使用Theme.AppCompat下面的一个主题包,如:
<activity android:theme="@style/Theme.AppCompat.Light" ... >
这时,在API level大于等于7的机器上,我们的Activity就包含了ActionBar了。
注意:在API level 11或以上的系统上,即targetSdkVersion
或minSdkVersion
属性设置为11或者以上时,Theme.Holo是默认主题,这个时所有的Activity都包含有ActionBar,如果你某个Activity不希望包含ActionBar,你可以设置这个Activity的主题为Theme.Holo.NoActionBar
。
1.1 移除ActionBar
你可以在运行时通过调用hide()方法动态去隐藏ActionBar。如:
ActionBar actionBar = getSupportActionBar();//在API>=11时,使用getActionBar()
actionBar.hide();
当ActionBar被隐藏之后,系统会调整我们的布局,以便全屏显示。你可以通过调用
show()方法重新显示ActionBar。
注意:隐藏和显示ActionBar都会导致系统重新布局我们的Activity。所以如果你需要频繁地去隐藏和显示ActionBar,你可能需要启用"遮盖模式"(overlay mode)。覆盖模式会将ActionBar绘制在Activity布局的前端,且覆盖Activity布局的上方。这个时候,当ActionBar被显示和隐藏的时候,我们的Activity只需要去控制marginTop。为了启用遮盖模式,我们需要创建一个自定义的主题,并且设置windowActionBarOverlay属性为true。
1.2 使用Logo替代app icon
默认情况下,系统会使用我们的应用图标作为ActionBar中的icon,也可以在<application>
或<activity>
标签中指定icon
属性。同时,你也可以指定logo
属性,然后ActionBar就会使用这个logo而不是icon。
一般logo会比icon要大,但是logo不应该包含一些不必要的文字。logo是一个用户品牌,而icon则是一个符合应用icon必须为正方形的logo修改版本。(比如圆形的logo,方形的icon)。
2. 添加行为动作(Action Items)
ActionBar可以让用户能直接使用那些和当前App上下文关联的最重要的行为动作。那些直接以icon或文本的形式出现在ActionBar中的视图称为动作按钮(Action Buttons)。一些不适合放在ActionBar上或不重要的Action都被放置到了action overflow中。用户可以通过点击右边的overflow按钮(有菜单按钮也可以点击菜单按钮)来展开这个Action列表。
当Activity启动的时候,系统会调用Activity的onCreateOptionsMenu()方法去填充ActionBar的Action items。使用这个方法可以加载一个定义了所有的Action items的菜单资源。比如说:
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()方法中加载这个资源到指定的Menu中,添加每一个item到ActionBar中:
@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 item以Action Button的形式直接出现在ActionBar上,需要在
<item>标签下包含
showAsAction="ifRoom"属性。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
<strong>xmlns:yourapp="http://schemas.android.com/apk/res-auto"</strong> >
<item android:id="@+id/action_search"
android:icon="@drawable/ic_action_search"
android:title="@string/action_search"
<strong>yourapp:showAsAction="ifRoom"</strong> />
...
</menu>
如果ActionBar上没有足够的空间给Action item显示,它就会出现在Action overflow中。
注意:在上面的例子中,showAsAction属性有引用到定义在<menu>标签中的名称空间。当使用定义在支持包中的XML属性时,这个是必须的,因为这些属性在Android早期的版本是不存在的。所以你必须使用你自己的名称空间作为定义在支持包中的XML属性的字头。
如果你给menu item提供了一个标题和icon,即设置了title
属性和icon
属性,那么Action item会默认只显示icon。如果你希望标题,那么你可以在showAsAction
属性中添加"withText"取值,如:
<item yourapp:showAsAction="ifRoom|withText" ... />
注意:
"withText"是给ActionBar的一个暗示,表示希望显示title文字。ActionBar会尽可能地去显示这个标题,但是如果icon可用且ActionBar没有足够的空间,那么这个标题也可能不会被显示。
即使你不声明action item显示标题,你也需要去定义title
属性,有如下几个原因:
【1】如果ActionBar没有足够的空间,overflow中的menu item可能只会显示title。
【2】屏幕阅读器给视力障碍的用户只显示Menu item的title。
【3】对于那些只显示了icon的action item,用户可以通过长按来显示title。
你也可以使用"always"取值来要求一个item总是以Action Button的形式展示在ActionBar上。但是你不应该这么去干,因为这样做在小屏设备上可能会导致一些布局问题,最好是使用"ifRoom"去替代。
2.1 处理Action item的点击事件
当用户点击了一个action,系统会回调我们Activity的onOptionsItemSelected()方法。这个方法传递了一个MenuItem
的参数,你可以通过它的getItemId()方法获取到其ID。这个id就是<item>标签的id属性。然后你可以根据这个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中加载了一个menu,即通过Fragment的onCreateOptionsMenu()方法,当用户点击了一个item的时候,系统会回调Fragment的onOptionsItemSelected()方法。但是,宿主Activity会优先获取到处理这个事件的权利,所以系统会先调用宿主Activity的