SAKA'S BLOG

使用APPBar

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:
    1
    2
    3
    public class MyActivity extends AppCompatActivity {
    // ...
    }

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

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    <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。 例如:
    1
    2
    3
    4
    5
    6
    7
    @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文件的代码示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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属性中声明的值相匹配。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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,并指定了父/子关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<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的“向上”按钮:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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小部件添加到应用程序栏中:

1
2
3
4
5
<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小部件的对象引用:

1
2
3
4
5
6
7
8
9
10
11
12
@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()。 例如,您可能希望根据是否展开或折叠操作视图来更新活动。 以下代码段显示了如何定义和传递侦听器:

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
29
30
@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,它是一个在支持库中定义的小部件,允许您的应用与其他应用程序共享数据:

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

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