使用操作视图和操作提供器

v7 appcompat 支持库 Toolbar 为用户提供了几种与应用进行互动的不同方式。之前的课程介绍了如何定义“操作”,操作既可以是按钮,也可以是菜单项。这节课介绍了如何添加两种多功能组件:

  • “操作视图”是一种能够在应用栏中提供丰富功能的操作。例如,借助搜索操作视图,用户可以在应用栏中输入搜索文字,而无需更改 Activity 或 Fragment。
  • “操作提供器”是一种具有自定义布局的操作。此操作一开始会显示为按钮或菜单项,但当用户点击此操作时,操作提供器便会以您想要定义的任何方式控制此操作的行为。例如,操作提供器可以通过显示菜单来响应点击。

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

添加操作视图

要添加操作视图,请在工具栏的菜单资源中创建 <item> 元素,如添加操作按钮中所述。请将以下两个属性中的一个添加到 <item> 元素:

  • actionViewClass:实现操作的微件的类。
  • actionLayout:描述操作组件的布局资源。

showAsAction 属性设为 "ifRoom|collapseActionView""never|collapseActionView"collapseActionView 标记用于指示当用户未与其进行互动时应该如何显示微件:如果微件位于应用栏中,则应用应该将微件显示为图标。如果微件位于溢出菜单中,则应用应该将微件显示为菜单项。当用户与操作视图进行互动时,它应该展开以填满应用栏。

例如,以下代码会将 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 指定的图标。(如果应用栏空间不足,则应用会将操作添加到溢出菜单中。)当用户点按图标或菜单项时,此微件会展开以填满工具栏,让用户能够与其互动。

图 1. 当用户点击某个操作视图的图标时,此视图的界面会填满工具栏。

如果您需要配置操作,请在 Activity 的 onCreateOptionsMenu() 回调中进行配置。您可以通过调用 getActionView() 方法来获取操作视图的对象引用。例如,以下代码可以获取在上一个代码示例中定义的 SearchView 微件的对象引用:

Kotlin

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.main_activity_actions, menu)

        val searchItem = menu?.findItem(R.id.action_search)
        val searchView = searchItem?.actionView as SearchView

        // Configure the search info and add any event listeners...

        return super.onCreateOptionsMenu(menu)
    }
    

Java

    @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) searchItem.getActionView();

        // Configure the search info and add any event listeners...

        return super.onCreateOptionsMenu(menu);
    }
    

响应操作视图展开行为

如果操作的 <item> 元素具有 collapseActionView 标记,则应用会将操作视图显示为图标,直到用户与操作视图互动为止。当用户点击图标时,内置的 onOptionsItemSelected() 处理程序便会展开操作视图。如果您的 Activity 子类替换 onOptionsItemSelected() 方法,则替换方法必须调用 super.onOptionsItemSelected() 以便让父类可以展开操作视图。

如果您想要在操作处于展开或收起状态时执行某项操作,则可以定义一个实现 MenuItem.OnActionExpandListener 的类,并将此类的某个成员传递给 setOnActionExpandListener()。例如,您可能需要根据操作视图是处于展开状态还是收起状态更新 Activity。以下代码段展示了如何定义和传递监听器:

Kotlin

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.options, menu)
        // ...

        // Define the listener
        val expandListener = object : MenuItem.OnActionExpandListener {
            override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
                // Do something when action item collapses
                return true // Return true to collapse action view
            }

            override fun onMenuItemActionExpand(item: MenuItem): Boolean {
                // Do something when expanded
                return true // Return true to expand action view
            }
        }

        // Get the MenuItem for the action item
        val actionMenuItem = menu?.findItem(R.id.myActionItem)

        // Assign the listener to that action item
        actionMenuItem?.setOnActionExpandListener(expandListener)

        // Any other things you have to do when creating the options menu...

        return true
    }
    

Java

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

添加操作提供器

要声明操作提供器,请在工具栏的菜单资源中创建 <item> 元素,如添加操作按钮中所述。添加 actionProviderClass 属性,并将其设为操作提供器类的完全限定类名。

例如,以下代码声明了 ShareActionProvider,这是支持库中定义的一个微件,可以让您的应用与其他应用共享数据:

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

在这种情况下,不必为此微件声明图标,因为 ShareActionProvider 提供了自己的图形。如果您使用的是自定义操作,则要声明图标。

若想详细了解如何创建自定义操作提供器,请参阅 ActionProvider 的参考文档。若想详细了解如何配置 ShareActionProvider,请参阅此类的参考文档。