Android应用程序开发——添加操作栏

 

添加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或者更高。例如:

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

注意:如果已经创建了一个自定义主题,就要确定它是否派生自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文件中,更新<application>元素或者某个的<activity>元素,以便使用其中一个Theme.AppCompat系列的主题。例如:

<activity android:theme="@style/Theme.AppCompat.Light" ... >

注意:如果已经创建了一个自定义主题,就要让它派生自Theme.AppCompat主题或者Theme.AppCompat主题的某一个派生主题。

 

现在,在Android 2.1(API level 7)或者更高版本上运行时,你的activity就包括了ActionBar。

 

记住在manifest中恰当地设定app的API level支持。

<manifest ... >
    <uses-sdk 
android:minSdkVersion="7" 
android:targetSdkVersion="18" />
    ...
</manifest>

 

 

添加操作项

ActionBar允许将对于当前界面最重要的操作作为像按钮一样添加到ActionBar中。这些操作项是直接显示在ActionBar上的,这些操作项由图标或者文本组成。对于那些因为ActionBar上无法容纳或者不够重要的操作项都被藏在操作菜单中。


 ActionBar,上面有Search和表明额外操作菜单的操作按钮

 

在XML中指定操作

ActionBar中的操作(包括在菜单里的操作)都定义在XMLmenu resource中。为把操作添加到ActionBar中,就要在项目的res/menu目录中创建一个新XML文件。

 

下面的例子演示了如何添加操作到状态栏,并且添加操作到菜单中。例如:

res/menu/main_activity_actions.xml

<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>

以上声明了在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

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <!-- Search, should appear as action button -->
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          yourapp:showAsAction="ifRoom"  />
    ...
</menu>

 

将操作填充到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匹配你在对应<item>元素的android: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,如下所示:

<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(),将图标作为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文件中,为<application>元素或者某个的<activity>元素声明这两个主题,你就可以将它们两个应用到整个app上,或者应用到某个activity上。

 

例如:

<application 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"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.Holo.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
    </style>

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

然后将主题应用到整个app或者单个activity上:

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

 

用于Android2.1或者更高版本

在使用Support Library时,必须如下所示地取代以上的同样主题:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.AppCompat.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/MyActionBar</item>

        <!-- Support library compatibility -->
        <item name="actionBarStyle">@style/MyActionBar</item>
    </style>

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

        <!-- Support library compatibility -->
        <item name="background">@drawable/actionbar_background</item>
    </style>
</resources>

然后将主题应用到整个app或者某个activity上:

<application 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"?>
<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>

 

用于Android2.1或者更高版本

在支持Support Library时,风格XML文件如下所示:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.AppCompat">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
        <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item>
        <item name="android:actionMenuTextColor">@color/actionbar_text</item>

        <!-- Support library compatibility -->
        <item name="actionBarStyle">@style/MyActionBar</item>
        <item name="actionBarTabTextStyle">@style/MyActionBarTabText</item>
        <item name="actionMenuTextColor">@color/actionbar_text</item>
    </style>

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

        <!-- Support library compatibility -->
        <item name="titleTextStyle">@style/MyActionBarTitleText</item>
    </style>

    <!-- ActionBar title text -->
    <style name="MyActionBarTitleText"
           parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textColor">@color/actionbar_text</item>
        <!-- The textColor property is backward compatible with the Support Library -->
    </style>

    <!-- ActionBar tabs text -->
    <style name="MyActionBarTabText"
           parent="@style/Widget.AppCompat.ActionBar.TabText">
        <item name="android:textColor">@color/actionbar_text</item>
        <!-- The textColor property is backward compatible with the Support Library -->
    </style>
</resources>

 

自定义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"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!-- 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" />
</selector>

 

仅用于Android3.0或者更高版本

仅在支持Android 3.0或者更高版本时,风格XML如下所示:

res/values/themes.xml

<?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>

 

用于Android2.1或者更高

在使用Support Library时,风格XML文件如下所示:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.AppCompat">
        <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item>

        <!-- Support library compatibility -->
        <item name="actionBarTabStyle">@style/MyActionBarTabs</item>
    </style>

    <!-- ActionBar tabs styles -->
    <style name="MyActionBarTabs"
           parent="@style/Widget.AppCompat.ActionBar.TabView">
        <!-- tab indicator -->
        <item name="android:background">@drawable/actionbar_tab_indicator</item>

        <!-- Support library compatibility -->
        <item name="background">@drawable/actionbar_tab_indicator</item>
    </style>
</resources>

更多资源

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主题(或者是其中一个衍生)作为父主题来使用。例如:

<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>

用于Android2.1或者更高版本

如果app对运行低于Android 3.0版本的设备上的兼容性使用Support Library,则自定义主题应当将Theme.AppCompat主题(或其中一个衍生)作为父主题来使用。例如:

<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.AppCompat">
        <item name="android:windowActionBarOverlay">true</item>

        <!-- Support library compatibility -->
        <item name="windowActionBarOverlay">true</item>
    </style>
</resources>

还要注意这个主题还包括对windowActionBarOverlay风格的两个定义:一个是有android:前缀,另一个则无。有android:前缀的定义是用于在平台中包括风格的Android版本,没有前缀的是用于从Support Library中读取风格的较早版本。

 

指定布局的顶部空白

当ActionBar处于覆盖模式中时,它可能会覆盖应当仍可见的部分布局。要确保那些项目一直处在ActionBar的下面,或添加空白,或使用由actionBarSize指定的高度填充到视图的顶部。例如:

<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>

如果对ActionBar使用Support Library,就需要移除android:前缀。例如:

<!-- 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值适用所有版本,包括Android 3.0以及更高版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值