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

Compose の方法を試す
Jetpack Compose は、Android で推奨される UI ツールキットです。Compose でコンポーネントを追加する方法について説明します。

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 をご覧ください。