添加ActionBar
ActionBar是最重要的设计元素之一,可以用它实现app的activity。它提供了数个用户界面特征,应用程序通过这些特征提供一些一致性的操作,这样用户就可以很快地熟悉你的应用程序了。关键功能包括:
l 一个专用的空间,用于标识你的应用程序,以及指明用于目前位于应用程序中的路径。
l 快速访问一些比较重要的功能(比如搜索)。
l 支持导航和视图转换(用tab或者下拉列表)。
这节提供了ActionBar的基本用法。
设置ActionBar
在ActionBar中显示的最基本的信息是activity的标题和左边的app图标。如下图的ActionBar中显示了一个应用图标和Activity的名字,这个信息将用于知会软件的使用者他们所在软件的位置,以及这个Activity的标识。
带有app图标和activity标题的ActionBar
设置基本的ActionBar要求app使用一个帮助你启用ActionBar的activity主题。如何使用这些主题,这取决于哪个Android版本是你的app所支持的最低版本。因此,本教程就依据这个分为两部分。
仅支持Android3.0及以上
由Android 3.0(API level 11)开始,ActionBar就包括在所有使用Theme.Holo主题(或由它派生出来的某一个主题)的activity中了。当targetSdkVersion或者minSdkVersion属性被设定为“11”或者更高时,这个主题就是默认的。
因此,要把ActionBar添加到activity,只要把属性设到11或者更高。例如:
...
注意:如果已经创建了一个自定义主题,就要确定它是否派生自Theme.Holo主题或者Theme.Holo派生出来的某一个主题。
现在,Theme.Holo主题就应用到你的app上了,App中的所有activity都将显示出ActionBar。
支持Android 2.1及以上
当在低于Android 3.0版本上运行时,添加ActionBar要求得在应用程序中包括Android Support Library。
app项目整合了Support Library之后,就要做到:
1、 更新activity,让它继承ActionBarActivity,例如:
public class MainActivity extends ActionBarActivity { ... }
2、 在manifest文件中,更新
android:theme="@style/Theme.AppCompat.Light" ... >
注意:如果已经创建了一个自定义主题,就要让它派生自Theme.AppCompat主题或者Theme.AppCompat主题的某一个派生主题。
现在,在Android 2.1(API level 7)或者更高版本上运行时,你的activity就包括了ActionBar。
记住在manifest中恰当地设定app的API level支持。
... >
android:minSdkVersion="7"
android:targetSdkVersion="18" /> ...
添加操作项
ActionBar允许将对于当前界面最重要的操作作为像按钮一样添加到ActionBar中。这些操作项是直接显示在ActionBar上的,这些操作项由图标或者文本组成。对于那些因为ActionBar上无法容纳或者不够重要的操作项都被藏在操作菜单中。
ActionBar,上面有Search和表明额外操作菜单的操作按钮
在XML中指定操作
ActionBar中的操作(包括在菜单里的操作)都定义在XMLmenu resource中。为把操作添加到ActionBar中,就要在项目的res/menu目录中创建一个新XML文件。
下面的例子演示了如何添加操作到状态栏,并且添加操作到菜单中。例如:
res/menu/main_activity_actions.xml
以上声明了在ActionBar有可用空间时,Search应当作为一个操作项显示在ActionBar上,但是Settings就应当始终出现在菜单中。(默认情况下,所有的操作都要显示在菜单中,但是为每个操作明确声明设计意图也是很好的实践。)
Icon属性需要一个资源ID对应一张图片。跟在@drawable后面的名字必须是已经在项目的res/drawable目录中保存的位图的名字。例如,"@drawable/ic_action_search"指的是ic_action_search.png。同样,title属性使用一个字符串资源,这个字符串资源是由项目中的res/values/目录中的XML文件所定义的。
注意:在为app创建图标和其它图片资源时,提供多个版本,每个版本为不同屏幕密度都做了优化,这是很重要的。
如果在对低至Android 2.1版本的兼容性使用Support Library时,那么showAsAction属性在android:namespace中就不可用。不用Support Library提供这个showAsAction属性,而必须是你自己定义XML名字空间,并将那个名字空间作为属性的前缀来使用。(自定义的XML名字空间应该是基于app名称的,但是它也可以是你想要的任何一个名字,而且只在你声明该名字空间的文件范围里才可入。)例如:
res/menu/main_activity_actions.xml
将操作填充到ActionBar上
将菜单项置于ActionBar中,在activity中实现onCreateOptionsMenu()回调方法,用来将菜单资源填充到给定的Menu对象中。例如:
@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); }
响应ActionBar
当用户按下其中一个操作项或者操作菜单中的某一个项目时,系统就调用activity的onOptionsItemSelected()回调方法。在该方法的实现中,系统通过该方法的MenuItem对象告诉Activity用户点击的是哪一项,菜单ID是菜单的唯一标识,我们可以通过MenuItemt的getItemId()方法获取操作项ID——getItemId方法返回的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_settings: openSettings(); return true; default: return super.onOptionsItemSelected(item); } }
为低等级activity添加Up按钮
App中那些不是app入口(activity不是“home”屏幕)的所有activity,通过按下ActionBar中的Up按钮,它们应给用户提供一个导航到app层次结构中父Activity的方法。
Gmail中的Up按钮
当在Android 4.1(API Level)或者更高版本上运行时,或者在从Support Library中使用ActionBarActivity时,操作Up导航仅需要你在manifest文件中声明父activity,并为ActionBar启用Up按钮。
例如,如何在manifest中声明一个activity的父Activity,如下所示:
... >
...
android:name="com.example.myfirstapp.MainActivity" ...>
...
android:name="com.example.myfirstapp.DisplayMessageActivity"
android:label="@string/title_activity_display_message"
android:parentActivityName="com.example.myfirstapp.MainActivity" >
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
然后通过调用setDisplayHomeAsUpEnabled(),将图标作为Up按钮启用:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_displaymessage); getSupportActionBar().setDisplayHomeAsUpEnabled(true); // If your minSdkVersion is 11 or higher, instead use: // getActionBar().setDisplayHomeAsUpEnabled(true); }
现在由于系统知道MainActivity是DisplayMessageActivity的父activity,当用户按下Up按钮时,系统就适当地导航到父activity——你不需要处理Up按钮的事件。
定制化ActionBar
ActionBar给用户提供了一个熟悉和可预见的方法,用来执行操作并导航app,但是并不意味着它需要和在其它app中所做的完全一样。如果想要对ActionBar设计风格,以便更加适应产品品牌,通过使用Android的style and theme资源就可以轻易做到。
Android包括了几个内置activity主题,这些主题包括了“dark”或者“light”的ActionBar风格。你也可以为ActionBar扩展这些主题来更进一步地自定义外观。
注意:如果你在对ActionBar使用Support Library APIs,则就必须使用(或覆盖)Theme.AppCompat系列的风格(而非Theme.Holo系列风格,他们仅在API level或者更高级别的时候可用)。在此过程中,声明的每个风格属性必须被声明两次:一次是在使用平台的风格属性(android:属性)时,一次是在使用包含在Support Library里的风格属性时。详情见下面的例子。
使用Android主题
Android包括了两个基线的activity主题,它们表明了ActionBar的颜色。
l “dark”主题的Theme.Holo
l “light”主题的Theme.Holo.Light
通过在有android:theme属性的manifest文件中,为
例如:
android:theme="@android:style/Theme.Holo.Light" ... />
通过使用Theme.Holo.Light.DarkActionBar主题实现activity的其它部分使用light的颜色主题的同时使用dark的ActionBar。
在使用Support Library的时候,必须改用Theme.AppCompat主题:
l Theme.AppCompat用于”dark”主题
l Theme.AppCompat.Light用于”light”主题
l Theme.AppCompat.Light.DarkActionBar用于darkActionBar的light主题
自定义背景
要改变ActionBar背景就要为某个Activity定制化一个主题,这个主题需要你重写actionBarStyle属性。这个属性指向另一个风格,在那里,你可以覆盖background属性来为ActionBar背景指定一个drawable资源。
如果你的app使用了navigation tabs或者split action bar(分拆ActionBar),则分别使用backgroundStacked和backgroundSplit属性,也可以为这些栏指定背景。
注意:声明一个恰当的父主题很重要,自定义主题和风格从中继承它们的风格。没有这个父风格,只有你自己明确声明这些风格属性,ActionBar才会有这些属性。
仅用于Android3.0或者更高版本
在仅支持Android 3.0或者更高版本时,你可以定义ActionBar的背景,如下所示:
res/values/themes.xml
xml version="1.0" encoding="utf-8"?>
然后将主题应用到整个app或者单个activity上:
android:theme="@style/CustomActionBarTheme" ... />
用于Android2.1或者更高版本
在使用Support Library时,必须如下所示地取代以上的同样主题:
res/values/themes.xml
xml version="1.0" encoding="utf-8"?>
然后将主题应用到整个app或者某个activity上:
android:theme="@style/CustomActionBarTheme" ... />
自定义文本颜色
要在ActionBar中修改文本颜色,需要为每个文本元素覆盖单独的属性:
l ActionBar标题:创建一个指定textColor属性的自定义风格,并在自定义actionBarStyle中为titleTextStyle指定这个风格。
注意:应用于titleTextStyle的自定义风格应该将TextAppearance.Holo.Widget.ActionBar.Title作为父风格来使用。
l ActionBar的tabs:在activity主题中覆盖actionBarTabTextStyle。
l 操作项:在activity主题中覆盖actionMenuTextColor。
仅用于Android3.0或者更高版本
在仅支持Android 3.0或者更高版本时,你可以定义ActionBar的背景,如下所示:
res/values/themes.xml
xml version="1.0" encoding="utf-8"?>
用于Android2.1或者更高版本
在支持Support Library时,风格XML文件如下所示:
res/values/themes.xml
xml version="1.0" encoding="utf-8"?>
自定义tab指示器
要改变用于导航tab的指示器,则创建一个覆盖actionBarTabStyle属性的activity主题。这个属性指向另一个风格资源,在那里,你可以覆盖应指定一个状态列表drawable的background属性。
注意:状态列表drawable很重要,因此目前被选择的tab表明了它是有一个背景的状态,这不同于其它tab。关于如何创建一个处理多个按钮状态的drawable资源,参阅State List文档。
例如,这里有一个状态列表的drawable,它为ActionBartab的几种不同状态声明了一个特定的背景:
res/drawable/actionbar_tab_indicator.xml
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android"> - android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected" />
- android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected" />
- android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused" />
- android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_focused" />
- android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed" />
- android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed" />
- android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed" />
- android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed" />
仅用于Android3.0或者更高版本
仅在支持Android 3.0或者更高版本时,风格XML如下所示:
res/values/themes.xml
xml version="1.0" encoding="utf-8"?>
用于Android2.1或者更高
在使用Support Library时,风格XML文件如下所示:
res/values/themes.xml
xml version="1.0" encoding="utf-8"?>
更多资源
l 参见列在ActionBar指南中的ActionBar的更多风格属性。
l 在Styles andThemes指南中学习主题如何工作。
l 关于ActionBar的更多完整风格,试试AndroidAction Bar Style Generator
覆盖ActionBar
默认情况下,通过稍稍减少剩余activity布局的可用空间量,ActionBar就显示在activity窗口的顶部。在用户交互期间,如果想要隐藏、显示ActionBar,可以通过调用ActionBar的hide()和show()来完成。但是,这就导致activity在新尺寸基础上,重新计算并绘制布局。
为避免在ActionBar隐藏和显示时调整布局尺寸,你就可以为ActionBar启用overlay mode(覆盖模式)。在覆盖模式中,activity布局使用了所有可用的空间,如同ActionBar不存在一样,并且系统还在布局的前面绘制ActionBar。这就在顶部覆盖了一些布局,但是现在当ActionBar隐藏或者显示的时候,系统就不需要调整布局的尺寸,过渡也是无缝的。
覆盖模式中的Gallery的ActionBar
提示:如果想要布局在ActionBar后面部分可见,就要为有部分透明背景的ActionBar创建一个自定义风格,如在图3中显示的这张图片。
启用覆盖模式
要为ActionBar启用覆盖模式,需要创建一个能扩展已存在ActionBar主题的自定义主题,并将android:windowActionBarOverlay属性设为true。
仅用于Android3.0或者更高版本
如果把minSdkVersion设了11或者更高,则自定义主题应该将Theme.Holo主题(或者是其中一个衍生)作为父主题来使用。例如:
用于Android2.1或者更高版本
如果app对运行低于Android 3.0版本的设备上的兼容性使用Support Library,则自定义主题应当将Theme.AppCompat主题(或其中一个衍生)作为父主题来使用。例如:
还要注意这个主题还包括对windowActionBarOverlay风格的两个定义:一个是有android:前缀,另一个则无。有android:前缀的定义是用于在平台中包括风格的Android版本,没有前缀的是用于从Support Library中读取风格的较早版本。
指定布局的顶部空白
当ActionBar处于覆盖模式中时,它可能会覆盖应当仍可见的部分布局。要确保那些项目一直处在ActionBar的下面,或添加空白,或使用由actionBarSize指定的高度填充到视图的顶部。例如:
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?android:attr/actionBarSize">
...
如果对ActionBar使用Support Library,就需要移除android:前缀。例如:
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">
...
在这种情况下,没有前缀的?attr/actionBarSize值适用所有版本,包括Android 3.0以及更高版本。