工具栏(action bar)是Android设计很重要的元素,他提供一致的UI特性让你的app对用户亲切,通过提供不同Android app间的一致性 关键函数包括:

  • 给你的app一个身份并表明用户位置的专用空间
  • 重要Activity的访问(Access)(例如搜索)
  • 对导航和视图切换的支持(标签页或下拉列表)

1.设置工具栏


在大多数情况下,actionbar显示Activity的标题和app图标在左边.就算在这个简单形式下,actionbar都可以让用户知道他们在哪里,和保持一致的身份(identity).

Figure 1. An action bar with the app icon and activity title.

设置一个基础的actionbar需要使用一个Activity主题允许actionbar. 如何请求决定于你app所支持的最低Android版本. 有两个分类,一个是Android3.0或更高, 另一个是Android2.1或更高.由于我坚决不开发低于4.0的版本,所以第二部分略去,详见这里

支持Android3.0或更高

Android 3.0 (API level 11)开始,actionbar被包含在所有使用Theme.Holo主题的Activity中,需要将targetSdkVersion或minSdkVersion属性设置到"11"或更高. 那么想要增加actionbar, 只需简单将属性设置到11或更高.例:

1
2
3
<manifest ... >
    <uses-sdk android:minSdkVersion="11" ... />
    ...</manifest>

注意: 如果你使用一个经典主题,确保它使用 Theme.Holo主题中的一个作为它的父主题.详见Styling the Action Bar 这样就行了,所有Activity会显示actionbar.

2.添加Action按钮


Actionbar是android设计中很关键的元素. 他允许你增加与目前环境相关的action items. 那些直接出现在actionbar的,是图标, 或文本或action 按钮. 那些不重要的Action 会放在下拉菜单(Action overflow).

Figure 1. An action bar with an action button for Search and the action overflow, which reveals additional actions.

在XML中定制Action

所有在action overflow的action按钮和其他可用item都定义在一个XML menu resource. 增加action到action bar, 创建一个XML文件在res/menu/目录下 增加一个;ltitem;gt元素到每个你想要增加到action bar的item. 例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <!\-\- Search, should appear as action button -->
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic\_action\_search"
          android:title="@string/action_search"
          android:showAsAction="ifRoom" />
    <!\-\- Settings, should always be in the overflow -->
    <item android:id="@+id/action_settings"
          android:title="@string/action_settings"
          android:showAsAction="never" />
</menu>

以上声明,当action bar的空间可用,Search action应该以一个action按钮出现.而Setting Action始终出现在overflow中.(默认下,所有的action出现在overflow。但是为每个action明确声明你的设计意图,是个好做法。) icon属性需要图片的资源ID. 在目录 @drawable 的名字必须与你保存在res/drawable/目录下的位图图像的名字一致.例如

添加Action到Action Bar

当你需要添加Menu按钮到Actionbar,需要用到onCreateOptionsMenu()这个回调方法,扩展Menu资源到给定的Menu对象.例如:"@drawable/ic_action_search"指向ic_action_search.png. 同样地, title属性需要一个string资源,定义在位于 res/values/目录下的XML文件中, 详见Building a Simple User Interface. 注意: 当创建icon和其他位图图像,关键要提供多种版本的屏幕分辨率.详见Supporting Different Screens. res/menu/main_activity_actions.xml

1
2
3
4
5
6
7
@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按钮

当用户在action overflow上点击任何一个按钮或条目(item)时,系统会调用onOptionsItemSelected() 回调方法.在这个方法中, 给定的 MenuItem上调用 getItemId()来决定哪个item被点击–返回的ID匹配你在相应的;ltitem;gt元素的 android:id 属性值.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@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按钮

Figure 4. The Up button in Gmail.

所有不是主入口的界面(不是"home"界面的活动)应当提供用户一个途径(way).通过点击(press)在actionbar 的Up button 让用户导航到app层次的逻辑父界面. 当使用Android 4.1 (API level 16) 或更高, 使用Support Library里的ActionBarActivity, 执行Up 导航仅需要你在manifest声明了父activity,并启用Up按钮. 例如以下是教你如何在manifest中声明activity的父亲:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<application ... >
    ...
    <!\-\- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.myfirstapp.MainActivity" ...>
        ...
    </activity>
    <!\-\- A child of the main activity -->
    <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
        android:label="@string/title\_activity\_display_message"
        android:parentActivityName="com.example.myfirstapp.MainActivity" >
        <!\-\- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>
</application>

通过调用 setDisplayHomeAsUpEnabled(),启用app图标作为Up button :

1
2
3
4
5
6
7
8
@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的父活动, 那么当用户按下Up button,系统会正确的回到父activity– 你不需要操作Up button的事件. 更多关于导航,见Providing Up Navigation.

3.设计Action Bar


actionbar 提供给用户一个亲近可预测的方式来呈现action和导航你的应用, 但是那不意味着它需要看看起都一样, 可以对其进行设计,来更好的符合你app的风格.使用Android的style and theme资源. Android包含一些内建的活动主题包括"dark"或"light"Actionbar 风格. 你可以扩展和定制这些外观. 注意: 如果你使用Support Library API, 那么你必须使用(或重载)Theme.AppCompat风格系(family)(而不是 Theme.Holo,在API level 11 上可用).在这种情况下,你必须声明两次每个风格属性:一次使用平台风格属性(adroid: 属性),另一次使用Support Library里的属性(appcompat.R.attr属性).详见以下例子.

使用Android主题

Android包括两个基线(baseline)activity主题,用来表征actionbar的颜色.

  • Theme.Holo for a “dark” theme.
  • Theme.Holo.Light for a “light” theme.

你可以应用这些主题到你整个app中,或者某个单独的活动. 通过在manifest文件中为元素或者元素声明android:theme属性 例:

<application android:theme="@android:style/Theme.Holo.Light" … />

你也可以使用dark Action bar, 余下的activity同时使用light 颜色通过声明Theme.Holo.Light.DarkActionBar 主题. 如果你在使用Support Library,你必须使用 Theme.AppCompat主题.

  • Theme.AppCompat for the “dark” theme.
  • Theme.AppCompat.Light for the “light” theme.
  • Theme.AppCompat.Light.DarkActionBar for the light theme with a dark action bar.

确保你使用正确的颜色对比. Action Bar Icon Pack包含light和dark两种标准图标.

自定义背景

改变actionbar的背景,创建一个自定义主题,通过重载(override)actionBarStyle属性. 这个属性指向另一个风格当你能重载background属性为actionbar背景制定一个可绘制的资源. 如果你的app使用navigation tabs或者 split action bar, 那么你也可以通过使用backgroundStackedbackgroundSplit, 为这些bars制定背景. 警告: 声明一个合适的父主题来让你的自定义主题和风格继承,这很重要. 没了父主题,你的actionbar将会少了很多风格属性,除非你明确地声明它们

针对Android3.0或以上版本

当使用Android3.0或以上版本,你可以如下定义actionbar的背景 res/values/themes.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!\-\- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.Holo.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
    </style>

    <!\-\- ActionBar styles -->
    <style name="MyActionBar"
           parent="@style/Widget.Holo.Light.ActionBar.Solid.Inverse">
        <item name="android:background">@drawable/actionbar_background</item>
    </style>
</resources>

然后应用你的主题到你整个app上或单独的activity

<application android:theme="@style/CustomActionBarTheme" … />

自定义文本颜色


为了改变actionbar上的文本颜色,需要为每个text元素重载分别的属性

  • actionbar 标题: 创建一个自定义风格,在你的自定义actionBarStyle中,指定textColor属性和为titleTextStyle属性指定风格Note: 自定义风格应用到titleTextStyle 应该使用 TextAppearance.Holo.Widget.ActionBar.Title 作为父风格.
  • Actionbar 标签页:重载actionBarTabTextStyle元素在你的activity主题
  • Action按钮: 重载actionMenuTextColor在你的activity主题.

对于Android 3.0或以上

当使用Android3.0或以上版本,你的风格XML应如下: res/values/themes.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!\-\- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.Holo">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
        <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item>
        <item name="android:actionMenuTextColor">@color/actionbar_text</item>
    </style>

    <!\-\- ActionBar styles -->
    <style name="MyActionBar"
           parent="@style/Widget.Holo.ActionBar">
        <item name="android:titleTextStyle">@style/MyActionBarTitleText</item>
    </style>

    <!\-\- ActionBar title text -->
    <style name="MyActionBarTitleText"
           parent="@style/TextAppearance.Holo.Widget.ActionBar.Title">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>

    <!\-\- ActionBar tabs text styles -->
    <style name="MyActionBarTabText"
           parent="@style/Widget.Holo.ActionBar.TabText">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>
</resources>

自定义标签指示器(indicator)

为了改变指示器,适用于 navigation tabs,创建一个actionBarTabStyle属性. 这个属性指向另一个风格资源 在哪个你重载background属性 ,它应该指定一个状态列表(state-list)可绘制. 注意: 例如,这里有个规定列表可绘制,生命了一个指定的背景图片,对于一个按抽屉哦哦呢bar标签页的几个不同的状态列表. res/drawable/actionbar_tab_indicator.xml

<!-- STATES WHEN BUTTON IS NOT PRESSED –>

<!\-\- Non focused states -->
<item android:state\_focused="false" android:state\_selected="false"
      android:state_pressed="false"
      android:drawable="@drawable/tab_unselected" />
<item android:state\_focused="false" android:state\_selected="true"
      android:state_pressed="false"
      android:drawable="@drawable/tab_selected" />

<!\-\- Focused states (such as when focused with a d-pad or mouse hover) -->
<item android:state\_focused="true" android:state\_selected="false"
      android:state_pressed="false"
      android:drawable="@drawable/tab\_unselected\_focused" />
<item android:state\_focused="true" android:state\_selected="true"
      android:state_pressed="false"
      android:drawable="@drawable/tab\_selected\_focused" />

<!-- STATES WHEN BUTTON IS PRESSED –>

<!\-\- Non focused states -->
<item android:state\_focused="false" android:state\_selected="false"
      android:state_pressed="true"
      android:drawable="@drawable/tab\_unselected\_pressed" />
<item android:state\_focused="false" android:state\_selected="true"
    android:state_pressed="true"
    android:drawable="@drawable/tab\_selected\_pressed" />

<!\-\- Focused states (such as when focused with a d-pad or mouse hover) -->
<item android:state\_focused="true" android:state\_selected="false"
      android:state_pressed="true"
      android:drawable="@drawable/tab\_unselected\_pressed" />
<item android:state\_focused="true" android:state\_selected="true"
      android:state_pressed="true"
      android:drawable="@drawable/tab\_selected\_pressed" />

针对Android 3.0或以上

当使用Android3.0或以上版本,你的风格XML应如下: res/values/themes.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!\-\- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.Holo">
        <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item>
    </style>

    <!\-\- ActionBar tabs styles -->
    <style name="MyActionBarTabs"
           parent="@style/Widget.Holo.ActionBar.TabView">
        <!\-\- tab indicator -->
        <item name="android:background">@drawable/actionbar\_tab\_indicator</item>
    </style>
</resources>

更多资源

4.重叠(overlay)actionbar


默认下actionbar出现在你activity窗口的顶部, 轻微地减少你activity布局的可用空间. 如果在用户交互的过程中, 你想隐藏和显示actionbar, 你可以调用hide() 和 show() . 然而, 这导致你的activity对布局基于它的新尺寸进行重计算和重绘.

Figure 1. Gallery’s action bar in overlay mode.

为了避免在隐藏和显示actionbar时改变布局的大小,你可以启用_overlay 模式_. 在overlay 模式下, activity布局使用所有的可用空间好像actionbar不不在,而且系统绘制actionbar在你layout的顶层. 这遮暗顶部的部分布局,但是当Actionbar隐藏或出现时,系统不会改变布局的大小,而且过渡平滑. **提示:**如果你想你的布局在actionbar后部分可见, 那么用半透明背景为actionbar创建一个自定义风格, 例如Figure 1所示. 更多如何定义Actionbar背景的信息,见 Styling the Action Bar.

启动overlay模式

为了启用overlay模式,你需要创建一个自定义主题, 扩展一个存在的Actionbar主题,并设android:windowActionBarOverlay属性值为true.

针对Android 3.0或更高

如果你的 minSdkVersion值为11或更好, 你的自定义主题应使用 Theme.Holo 主题(或者它的后代)作为你的父主题. 例如:

1
2
3
4
5
6
7
<resources>
    <!\-\- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.Holo">
        <item name="android:windowActionBarOverlay">true</item>
    </style>
</resources>

当Actionbar在overlay模式下, 他可能遮掩你布局的那本该保持可见的部分. 为了确保那些项目总是保持在你actionbar 下面,使用 由actionBarSize定义高度, 为视图顶部增加margin或者padding. 例如:

1
2
3
4
5
6
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout\_width="match\_parent"
    android:layout\_height="match\_parent"
    android:paddingTop="?android:attr/actionBarSize">
    ...
</RelativeLayout>

如果你使用Support Library, 你需要移除 android: 前缀. 例如:

1
2
3
4
5
6
7
<!\-\- Support library compatibility -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout\_width="match\_parent"
    android:layout\_height="match\_parent"
    android:paddingTop="?attr/actionBarSize">
    ...
</RelativeLayout>

这种情况下, 没有前缀的值?attr/actionBarSize 在各个版本可用, 包括3.0和以上.