Skip to content

Latest commit

 

History

History
529 lines (424 loc) · 24.3 KB

File metadata and controls

529 lines (424 loc) · 24.3 KB

2.添加ActionBar

ActionBar是你可以为应用Activity实现的重要设计元素之一。它提供了几个便捷的UI特性可以与其他的应用保持一致以便用户能更熟悉的使用。主要包括以下几个特点:

  • 一个明确的空间显示当前在应用中的位置。
  • 提供了快捷的方式来访问重要的内容(比如搜索)。
  • 支持导航和视图切换(通过不同的tabs或者下拉列表)。

image

创建Action Bar

Action Bar最基本的样式就是显示当前Activity的标题并在标题左侧显示应用程序图标,即便是这最基本的样式对所有的Activity来说也是非常有用的,因为可以告诉用户当前他们所处的位置而且还能为应用保持一个统一的标识。
image

创建一个基本的Action Bar需要应用使用支持Action Bar的一个activity主题。如何去声明这个主题就依赖于应用所支持的最低Android版本。所以接下来就以所支持的最低版本来分两部分进行介绍。

###支持Android 3.0及以上版本

Android 3.0(API lever 11)开始,在targetSdkVersionminSdkVersion是11或者更高的默认主题Theme.Holo(以及所有的子主题)中都是包含Action Bar的。

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

**Note:**如果自定义一个主题,一定要让Theme.Holo作为该主题的父主题。

现在应用使用了Theme.Holo主题,所有的页面都显示了Action Bar.

###支持Android 2.1及以上版本

Android3.0以下的版本中添加Action Bar需要在应用中添加Android Support包。

开始之前,通过阅读 Support Library Setup文档来建立v7 appcompat library(下载完library包之后,按照Adding libraries with resources的指引进行操作)。

一旦工程中集成了Support包:

  1. 更新Activity让其继承ActionBarActivity。例如:
    public class MainActivity extends ActionBarActivity { ... }
  2. manifest文件中更新<application>或单独的<activity>标签来使用Theme.AppCompat主题,例如:
    <activity android:theme="@style/Theme.AppCompat.Light" ... >

    Note: 如果自定义主题,要以Theme.AppCompat作为父主题。

到此,在Android2.1上运行时页面就会显示Action Bar.

切记,在manifest文件中要正确的设置所支持的API level

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

添加Action按钮

Action Bar允许你为当前程序上下文中重要的操作添加按钮。那些直接出现在 Action Bar中的icon/或文本就是action buttons(操作按钮)。显示不开的或不够重要的操作就会被隐藏在action overflow中。
image

###在XML中指定Actions

所有的Action Buttons或者其他在Action overflow中的action都是在XML中的menu resource里面声明的。在项目中的res/menu/目录可以创建一个新的XML文件,可以为Action Bar添加action.

对每个想在Action Bar中添加的条目对添加一个<item>标签,例如:

<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中能显示出来的话搜索功能会作为一个动作按钮显示出来,但是设置功能会一直显示在overflow中。(默认情况下,所有的动作都显示在overflow中,但是为每一个动作都指定明确的意图是一个非常好的习惯)

icon属性需要一个图片的资源ID@drawable/后面的名字必须与项目中res/drawable/目录中保存的图片名字一致。例如:@drawable/ic_action_search指向了ic_action_search.png。同样,title属性也需要一个在工程中res/values/XML文件所指定的文字资源。

< **Note:**在程序中创建图标或者其他的一些图片时,最好能更具不同的屏幕分辨率提供多个版本的图片。

如果为了支持Android2.1中使用了Support包,showAsAction属性不能在android这个命名空间下使用。Support包会提供这个属性,你需要在XML中声明对应的命名空间,并且用该命名空间的前缀。(一个自定义的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>

###为Action Bar添加操作

为了能让在菜单布局中的内容显示到Action Bar中,需要在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);
}

###响应操作按钮

当点击Action Button或者其他在overflow中的按钮时,系统会回调到当前ActivityonOptionsItemSelected()方法中。在该方法的实现中,可以通过参数中的MenuItemgetItemId()方法来获取到当前被点击的条目-返回的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);
    }
}

###为下级页面添加向上按钮

程序中除主入口之外素有的页面都需要在Action Bar中为用户提供一个导航到逻辑父屏的Up button(向上按钮)。
image 当运行在Android4.1(API level 16)或更高版本,或者使用Support包中的 ActionBarActivity时,实现向上导航需要在manifest文件中声明父 activity并且在action bar开启向上按钮功能。

例如,下面就是如何在manifest文件中声明父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 button功能:

@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);
}

由于系统已经知道MainActivityDisplayMessageActivity的父activity,当用户按下向上按钮时,系统会导航到对应的父activity,不需要去处理向上按钮的事件。

自定义Action Bar样式

Action Bar为用户提供一种熟悉可预测的方式来展示操作和导航,但是这并不意味着你的应用要和其他应用看起来一致。如果想将Action bar设计的合乎产品定位,只需简单地使用Android样式和主题资源。

Android包含少量的内置主题,有一些Action Bar样式。也可以继承这些主题去进行更深度的自定义Action Bar的样式。

< **Note:**如果使用Support包的API来实现Action Bar,就必须使用(或重写)Theme.AppCompat家族的样式(而不是在API11及以上的Theme.Holo家族)。如此一来,你声明的每一个样式属性都必须被声明两次:一次使用系统平台的样式属性(android:属性),另一次使用Support包中的样式属性(appcompat.R.attr 属性-这些属性的上下文其实就是你的app

###使用Android主题

Android包含两个基本的 Activity主题指明Action Bar的颜色:

  • Theme.Holo是一个暗的主题。
  • Theme.Holo.Light是一个淡的主题。

image

可以在manifest文件中的<application><activity>标签的android:theme属性来对整个应用或某个页面使用该主题。例如:

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

你可以通过声明activity的主题为Theme.Holo.Light.DarkActionBar来达到action bar为暗色,其他部分为淡色的样式。
image

在使用Support包时,必须要使用Theme.AppCompat类的主题:    

  • Theme.AppCompat为暗色的主题。
  • Theme.AppCompat.Light为淡色的主题
  • Theme.AppCompat.Light.DarkActionBar是有暗色Action Bar的淡色主题。

###自定义背景

创建一个自定义的主题并且重写actionBarStyle属性来改变Action Bar的背景。这个属性指向了另外一个样式,你可以在该样式中重写background属性来指定一个Action Bar背景资源。
image

如果你的 app 使用了 navigation tabs 或 split action bar ,你也可以通过分别设置 backgroundStacked 和 backgroundSplit 属性来为这些条指定背景。

< Note: 为自定义主题和样式声明一个合适的父主题,这点很重要。如果没有父样式,你的Action Bar将会失去很多默认的样式属性,除非能显式的对他们进行声明。

#####Android3.0及以上版本

对于支持Android3.0及以上版本时,可以向下面这样定义Action Bar的背景:

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

应用主题到整个应用或单独的Activity:

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

#####对Android2.1及以上版本

在使用Support包时,与上面相同的主题必须如下进行操作:

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

将主题应用到整个应用或单独的Activity:

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

###自定义文字颜色

修改Action Bar中的文字颜色时需要对每个文字元素修改不同的属性:

  • Action bar title: 创建一个自定义样式,并指定textColor属性,同时在自定义的actionBarStyle中将titleTextStyle属性指定为刚才的自定义样式。 < **Note:**被应用到titleTextStyle的自定义样式应该使用 TextAppearance.Holo.Widget.ActionBar.Title作为父样式。
  • Action bar tabs:在主题中重写actionBarTabTextStyle
  • Action buttons:在主题中重写actionMenuTextColor

#####Android3.0及以上版本

当应用支持Android3.0及以上版本时,程序的样式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包时,你的样式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 Indicator

创建一个自定义主题,并重写actionBarTabStyle属性来改变navigation tabs 使用的指引器。该属性指向另一个样式资源;在该样式资源里可以通过指定state-list drawable来重写background属性。

image

< Note:state-list drawable有非常重要的功能,它可以通过不同的背景来指出当前选中的tab与其他tab的区别。更多内容请参考State List文档。

例如,这是一个state_list资源对action bar tab的几种不同状态分别指定了不同的背景图片。

<?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及更高版本

在支持Android3.0及更高版本时,下面的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包时,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>

Action Bar叠加

默认情况下,Action Bar显示在页面的顶部,会稍微地减少其他布局的可用有效空间。如果在交互过程中需要隐藏和显示Action bar,可以通过调用Action Bar中的hide()show()方法来实现。但是这样会导致Activity根据新尺寸重新计算并绘制。

为了避免在Action Bar隐藏和显示时需要重绘界面,可以为Action bar启用叠加模式(overlay mode)。在叠加模式下,所有可用的空间都会被布局占用,就像Action Bar不存在一样,Action bar会叠加在布局之上。这样布局顶部就会些被遮挡,但当Action bar隐藏或显示时,系统不再进行重绘。

< **Note:**如果希望Action bar下面的布局部分可见,可以创建一个背景部分透明的自定义样式,如图所示:
image

###开启叠加模式

想要开启Action Bar的叠加模式,需要继承已经存在的Action Bar样式创建一个自定义的样式,并且将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>

#####在Andorid2.1及以上版本

如果应用程序支持Android3.0以下的版本,这时候自定义主题时需要使用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系统版本,不带前缀的适用于从Support库中读取式样的旧版本。

###指定布局的Top-margin

Action Bar启用叠加模式时,它可能会遮挡部分本应保持可见状态的布局。为了保证这些布局始终位于Action bar下方,可以使用actionBarSize属性来指定顶部marginpadding的高度来到达。例如:

<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包来创建Action Bar这里需要去掉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和更高的版本。