アクション ビューとアクション プロバイダを使用する

AndroidX ライブラリの Toolbar には、ユーザーがアプリを操作するさまざまな方法が用意されています。アクションを追加して処理するでは、アクション(ボタンまたはメニュー アイテム)を定義する方法について説明します。このドキュメントでは、次の 2 つの多用途コンポーネントを追加する方法について説明します。

  • アクション ビューは、アプリバー内に豊富な機能を提供するアクションです。たとえば、検索アクション ビューを使用すると、ユーザーはアクティビティやフラグメントを変更することなく、アプリバーに検索テキストを入力できます。
  • アクション プロバイダは、独自にカスタマイズされたレイアウトを持つアクションです。アクションは、最初はボタンまたはメニュー項目として表示されます。ユーザーがアクションをタップすると、定義した方法でアクション プロバイダの動作が制御されます。たとえば、アクション プロバイダがタップに応答してメニューを表示する場合などです。

AndroidX には、特別なアクション ビューとアクション プロバイダ ウィジェットがいくつか用意されています。たとえば、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="androidx.appcompat.widget.SearchView" />

ユーザーがウィジェットを操作していない場合、アプリは android:icon で指定されたアイコンとしてウィジェットを表示します。アプリバーにスペースがない場合、アプリはオーバーフロー メニューにアクションを追加します。

検索バーと、先頭と末尾にアイコンが表示されている画像。
図 1. 先頭と末尾にアイコンが表示された検索バー

ユーザーがアイコンまたはメニュー アイテムをタップすると、ウィジェットがツールバーに合わせて展開され、ユーザーが操作できるようになります。

検索バーにフォーカスを合わせると検索ビューが開かれていることを示す画像。
図 2. 検索バーがフォーカスされると、検索ビューが開きます。

アクションを設定する必要がある場合は、アクティビティの 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() の組み込みハンドラによってアクション ビューが開きます。アクティビティのサブクラスで onOptionsItemSelected() メソッドをオーバーライドする場合、スーパークラスがアクション ビューを展開できるように、オーバーライド メソッドで super.onOptionsItemSelected() を呼び出す必要があります。

アクションの展開時または折りたたみ時になんらかの処理を行うには、MenuItem.OnActionExpandListener を実装するクラスを定義し、そのクラスのメンバーを setOnActionExpandListener() に渡します。 たとえば、アクション ビューが開いているか閉じているかに基づいてアクティビティを更新できます。次のコード スニペットは、リスナーを定義して渡す方法を示しています。

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 the action item collapses.
            return true // Return true to collapse the action view.
        }

        override fun onMenuItemActionExpand(item: MenuItem): Boolean {
            // Do something when it expands.
            return true // Return true to expand the 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)

    // For anything else you have to do when creating the options menu,
    // do the following:

    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 the action item collapses.
            return true;  // Return true to collapse action view.
        }

        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // Do something when it expands.
            return true;  // Return true to expand the 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);

    // For anything else you have to do when creating the options menu,
    // do the following:

    return true;
}

アクション プロバイダを追加する

アクション プロバイダを宣言するには、アクションを追加して処理するで説明されているように、ツールバーのメニュー リソースに <item> 要素を作成します。actionProviderClass 属性を追加し、アクション プロバイダ クラスの完全修飾クラス名に設定します。

たとえば、次のコードは ShareActionProvider を宣言しています。これは AndroidX ライブラリで定義されたウィジェットで、アプリが他のアプリとデータを共有できるようにします。

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

この場合、ShareActionProvider が独自のグラフィックを提供するため、ウィジェットのアイコンを宣言する必要はありません。カスタム操作を使用する場合は、アイコンを宣言します。

参考情報

  • トップ アプリバーに共有アクションを追加する例については、ShareActionProvider をご覧ください。
  • カスタム アクション プロバイダの作成について詳しくは、ActionProvider をご覧ください。