如何使用 AppBar

5,001 阅读11分钟
原文链接: rgf456.github.io

APPBar是应用程序Activity中最重要的设计元素之一,因为它提供了用户熟悉的可视化结构和交互式元素。 使用APPBar,能保证你的应用程序与其他Android应用程序保持一致,允许用户快速了解如何操作你的应用程序。APPBar主要功能如下:

  1. 为您的应用提供ID并指示用户目前在应用中的位置的专用空间。
  2. 以可预测的方式访问重要的操作,例如搜索。
  3. 支持导航和视图切换(带选项卡或下拉列表)。

ActionBar示例

该课程介绍如何使用v7 appcompat支持库的“ToolBar”小工具作为APPBar。 还有其他方法来实现APPBar.例如,一些主题默认情况下将ActionBar设置为应用程序栏 - 但是使用appcompat ToolBar可以轻松设置适用于最广泛设备的APPBar,以及 随着应用程序开发,您还可以随时自定义AppBar。

设置APPBar

在最基本的形式中,ToolBar将在一侧显示Activity的标题,另一侧显示一个溢出菜单。 即使以这种简单的形式,ToolBar可为用户提供有用的信息,并有助于给予Android应用程序一致的外观。

Figure 1. An app bar with the app title and overflow menu.

从Android 3.0(API级别11)开始,使用默认主题的所有Activity都将ActionBar作为APPBar。然而,APPBar功能已逐渐添加到各种Android版本的ActionBar。 因此,根据设备正在使用的Android系统的版本,ActionBar的表现会有所不同。相比之下,支持库的APPBar版本添加了最新的功能,它们可以在任何可以使用支持库的设备上使用。

因此,应该使用支持库的ToolBar类来实现Activity的APPBar。使用支持库的ToolBar有助于确保应用程序在最广泛的设备上具有一致的行为。 例如,ToolBar在运行Android 2.1(API级别7)或更高版本的设备上提供MaterialDesign体验,但是ActionBar不支持MaterialDesign,除非设备正在运行Android 5.0(API级别21)或更高版本。

在Activity中添加ToolBar

以下步骤描述了如何将ToolBar设置为Activity的APPBar:

  1. 将v7 appcompat支持库添加到项目中,如支持库设置中所述。
  2. 确保Activity继承自AppCompatActivity:
    public class MyActivity extends AppCompatActivity {
      // ...
    }

Note:更改所有要使用ToolBar作为APPBar的应用中的Activity。

  1. 在manifest中,将 元素设置为使用appcompat的NoActionBar主题之一。 使用这些主题之一将阻止应用程序使用ActionBar类作为APPBar。 例如:

    <application    
        android:theme="@style/Theme.AppCompat.Light.NoActionBar"    
        />
  2. 在Activity的布局中添加ToolBar。例如,以下布局代码添加了一个ToolBar,并将其显示为浮动在Activity上方:

    < android.support.v7.widget.Toolbar
       android:id="@+id/my_toolbar"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       android:background="?attr/colorPrimary"
       android:elevation="4dp"
       android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
       app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

在Material Design规范中,建议APPBar应具有4dp的高度.
将ToolBar定位在Activity布局的顶部,将其用作APPBar。

  1. 在Activity的onCreate()方法中,调用setSupportActionBar()方法来设置。 此方法将ToolBar设置为Activity的APPBar。 例如:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
        setSupportActionBar(myToolbar);
        }

应用程序现在有一个基本的Toolbar。默认情况下,ToolBar仅包含应用程序的名称和溢出菜单。 选项菜单最初只包含“设置”项目。 您可以添加更多操作到操作栏和溢出菜单。

使用App Bar实用程序方法

将ToolBar设置为Activity的APPBar后,可以访问v7 appcompat支持库的ActionBar类提供的各种方法。这些方法可以让你做一些有用的事情,比如隐藏或者显示APPBar。

要使用ActionBar的方法,请调用Activity的getSupportActionBar()方法。 此方法返回对Appcompat ActionBar对象的引用。获得该引用后,你可以调用任何ActionBar方法来调整APPBar。 例如,要隐藏APPBar,请调用ActionBar.hide()。

为APPBar添加操作

APPBar允许添加供用户操作的按钮。此功能可将最重要的操作放在APPBar顶部的当前上下文中。例如,当用户正在查看他们的照片时,照片浏览应用程序可能会在顶部显示共享并创建相册按钮; 当用户查看一张照片时,应用程序可能会显示裁剪和过滤器按钮。

APPBar中的空间有限。如果应用程序添加的操作比适用于APPBar的操作控件更多,则APPBar会将超量的操作放置到溢出菜单。 该应用程序还可以指定一个操作应始终显示在溢出菜单中,而不是显示在APPbar上。

 Figure 1. An app bar with a single action button and an overflow menu.

添加操作按钮

ToolBar中所有的操作按钮包括溢出菜单按钮都在XML菜单资源中定义。 要向操作栏添加操作,请在项目的res / menu /目录中创建一个新的XML文件。

为要包含在ToolBar中的每个项目添加一个 元素,如菜单XML文件的代码示例所示:

< menu xmlns:android="http://schemas.android.com/apk/res/android" >
    < !-- "Mark Favorite", should appear as action button if possible -->
    < item
        android:id="@+id/action_favorite"
        android:icon="@drawable/ic_favorite_black_48dp"
        android:title="@string/action_favorite"
        app:showAsAction="ifRoom"/>
    < !-- Settings, should always be in the overflow -->
    < item android:id="@+id/action_settings"
          android:title="@string/action_settings"
          app:showAsAction="never"/>
< /menu>

上面代码中:showAsAction属性指定该操作按钮是否应显示为应用程序栏上的按钮。 如果您设置app:showAsAction =“ifRoom”(如示例代码Mark Favorite所示),则如果APPBar中有空间,该操作将显示为按钮; 如果没有足够的空间,超出的操作将被放置到溢出菜单。 如果您设置app:showAsAction =“never”(如示例代码的Settings所示),则该操作始终列在溢出菜单中,不会显示在应用程序栏中。

如果操作显示在应用程序栏中,系统将使用操作的图标作为操作按钮。

响应操作

当用户选择APPBar的一个按钮时,系统将调用ACtivity的onOptionsItemSelected()方法,并传递一个MenuItem对象以指示哪个项目被单击。 在执行onOptionsItemSelected()时,调用MenuItem.getItemId()方法来确定点击的是哪个项目。 返回的ID与您在相应的 元素的android:id属性中声明的值相匹配。

例如,以下代码检查以查看用户选择的操作。 如果该方法无法识别用户的操作,它将调用超类方法:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_settings:
            // User chose the "Settings" item, show the app settings UI...
            return true;
        case R.id.action_favorite:
            // User chose the "Favorite" action, mark the current item
            // as a favorite...
            return true;
        default:
            // If we got here, the user's action was not recognized.
            // Invoke the superclass to handle it.
            return super.onOptionsItemSelected(item);
    }
}

添加一个向上按钮

您的应用程序应该可以方便用户找到方法回到应用程序的主屏幕。 一个简单的方法是在应用程序栏上提供除主要功能之外的所有Activity的向上按钮。 当用户选择向上按钮时,应用程序将导航到父Activity。

本课程向您展示如何通过在清单中声明Activity的父级Activity,并启用APPBar的“向上”按钮,将一个向上按钮添加到Activity中。

声明一个父Activity

为了支持Activity中的功能,您需要声明Activity的父级。 您可以通过设置android:parentActivityName属性在应用程序清单中执行此操作。

Android 4.1(API级别16)中引入了android:parentActivityName属性。 要支持旧版本Android的设备,请定义一个 键值对,其名称为“android.support.PARENT_ACTIVITY”,值为父Activity的名称。

例如,假设你的应用程序有一个名为MainActivity的主要Activity和一个单独的子Activity。 以下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.MyChildActivity"
        android:label="@string/title_activity_child"
        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>

激活向上按钮

要启用具有父级Activity的Activity的向上按钮,请调用APPBar的setDisplayHomeAsUpEnabled()方法。 通常,您将在创建Activity时执行此操作。 例如,以下onCreate()方法将ToolBar设置为MyChildActivity的APPBar,然后启用该APPbar的“向上”按钮:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my_child);
    // my_child_toolbar is defined in the layout file
    Toolbar myChildToolbar =
        (Toolbar) findViewById(R.id.my_child_toolbar);
    setSupportActionBar(myChildToolbar);
    // Get a support ActionBar corresponding to this toolbar
    ActionBar ab = getSupportActionBar();
    // Enable the Up button
    ab.setDisplayHomeAsUpEnabled(true);
}

不需要在Activity的onOptionsItemSelected()方法中捕获up操作。 相反,该方法应该调用其超类,如“响应操作”中所示。 超类方法通过导航到父活动(如应用程序清单中指定)来响应向上选择。

操作视图

v7 appcompat支持库ToolBar提供了几种不同的方式供用户与应用程序交互。以前的课程描述了如何定义一个操作,可以是按钮或菜单项。本课介绍如何添加两个通用组件:

  • ActionView是在APPBar中提供丰富功能的操作。例如,搜索ActionView允许用户在应用栏中键入搜索文本,而不必更改Activity或fragment。
  • action provider是一个具有自己的定制布局的操作。该操作最初显示为按钮或菜单项,但是当用户单击操作时,action provider将以任何想要定义的方式控制操作的行为。例如,action provider可以通过显示菜单来响应点击。

Android支持库提供了几个专门的Action View和action provider小部件。例如,SearchView小部件实现用于输入搜索查询的操作视图,ShareActionProvider小部件实现与其他应用程序共享信息的操作。还可以定义自己的Action View和action provider。

添加一个Action View

要添加Action View,请在ToolBar的菜单资源中创建一个 元素. 将以下两个属性之一添加到 元素中:

  • actionViewClass:实现该操作的窗口小部件的类。
  • actionLayout:描述操作组件的布局资源。

showAsAction属性设置为ifRoom | collapseActionViewnever | collapseActionView。 collapseActionView标志指示当用户没有与其交互时如何显示窗口小部件:如果窗口小部件在APPBar上,应用程序应将该窗口小部件显示为图标。 如果窗口小部件位于溢出菜单中,应用程序应将窗口小部件显示为菜单项。 当用户与动作视图进行交互时,它会展开以填充应用栏。

例如,以下代码将SearchView小部件添加到应用程序栏中:

< item android:id="@+id/action_search"
     android:title="@string/action_search"
     android:icon="@drawable/ic_search"
     app:showAsAction="ifRoom|collapseActionView"
     app:actionViewClass="android.support.v7.widget.SearchView" />

如果用户没有与窗口小部件交互,则应用程序会将该窗口小部件显示为android:icon指定的图标。 (如果APPBar中没有足够的空间,应用程序会将操作添加到溢出菜单。)当用户点击图标或菜单项时,窗口小部件将展开以填充工具栏,允许用户与其进行交互。

Figure 1. When the user clicks an action view's icon, the view's UI fills the toolbar.

如果需要配置操作,请在Activity的onCreateOptionsMenu()回调中执行此操作。 您可以通过调用静态getActionView()方法获取操作视图的对象引用。 例如,以下代码将获取前一代码示例中定义的SearchView小部件的对象引用:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_activity_actions, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView =
            (SearchView) MenuItemCompat.getActionView(searchItem);
    // Configure the search info and add any event listeners...
    return super.onCreateOptionsMenu(menu);
}

响应Action View扩展

如果操作的 元素具有collapseActionView标志,则应用程序将Action View显示为图标,直到用户与操作视图进行交互。 当用户点击图标时,onOptionsItemSelected()的内置处理程序会扩展Action View。 如果Activity子类覆盖了onOptionsItemSelected()方法,则覆盖方法必须调用super.onOptionsItemSelected(),以便超类可以展开动作视图。

如果要在动作展开或折叠时执行某些操作,可以定义一个实现MenuItem.OnActionExpandListener的类,并将该类的成员传递给setOnActionExpandListener()。 例如,您可能希望根据是否展开或折叠操作视图来更新活动。 以下代码段显示了如何定义和传递侦听器:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.options, menu);
    // ...
    // Define the listener
    OnActionExpandListener expandListener = new OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            // Do something when action item collapses
            return true;  // Return true to collapse action view
        }
        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // Do something when expanded
            return true;  // Return true to expand action view
        }
    };
    // Get the MenuItem for the action item
    MenuItem actionMenuItem = menu.findItem(R.id.myActionItem);
    // Assign the listener to that action item
    MenuItemCompat.setOnActionExpandListener(actionMenuItem, expandListener);
    // Any other things you have to do when creating the options menu…
    return true;
}

添加一个Action Provider

要声明一个Action Provider,请在ToolBar的菜单资源中创建一个 元素,添加一个actionProviderClass属性,并将其设置为action provider类的完全限定类名。

例如,以下代码声明一个ShareActionProvider,它是一个在支持库中定义的小部件,允许您的应用与其他应用程序共享数据:

< item android:id="@+id/action_share"
    android:title="@string/share"
    app:showAsAction="ifRoom"
    app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>

在这种情况下,由于ShareActionProvider提供了自己的图标,因此无需再为它声明一个图标。 如果您使用自定义操作,请声明一个图标。