新增菜單

嘗試 Compose 方法
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何在 Compose 中新增元件。

選單是多種應用程式中的常見使用者介面元件。如要提供熟悉且一致的使用者體驗,請使用 Menu API 在活動中顯示使用者動作和其他選項。

顯示溢位選單範例的圖片
圖 1.輕觸圖示觸發的選單,會顯示在溢位選單圖示下方。

本文件說明如何在所有 Android 版本上建立三種基本選單或動作呈現:

選項選單和應用程式列
選項選單是活動選單項目的主要集合。在這裡,你可以放置會對應用程式造成全域影響的動作,例如「搜尋」、「撰寫電子郵件」和「設定」。

請參閱建立選項選單一節。

內容選單及關聯動作模式
內容選單是一種浮動式選單,會在使用者按住元素時顯示。這提供的一些操作會影響所選的內容或內容畫面。

關聯動作模式會在螢幕上方長條中顯示會影響所選內容的操作項目,並讓使用者選取多個項目。

請參閱建立內容選單一節。

彈出式選單
彈出式選單會顯示垂直項目清單,其中的項目會固定在叫用選單的檢視畫面中。這有助於提供與特定內容相關的操作溢位,或為指令的第二部分提供選項。在彈出式選單中的操作不會直接影響相對應的內容,這就是關聯動作的用途。相反地,彈出式選單適合在您的活動中,用來擴充與內容區域相關的操作。

請參閱建立彈出式選單一節。

在 XML 中定義選單

對於所有選單類型,Android 提供了標準 XML 格式來定義選單項目。請在 XML 選單資源中定義選單及其所有項目,而不要在活動的程式碼中建立選單。接著,您就可以在活動或片段中加載選單資源 (以 Menu 物件載入)。

使用選單資源是很好的做法,原因如下:

  • 在 XML 中可以更簡單明暸地看到選單結構。
  • 這會區隔選單內容與應用程式的行為程式碼。
  • 透過這個應用程式資源架構,可為不同的平台版本、螢幕大小和其他設定,建立不同的選單設定。

如要定義選單,請在專案的 res/menu/ 目錄中建立 XML 檔案,並使用下列元素建立選單:

<menu>
定義一個 Menu,這是選單項目使用的容器。<menu> 元素必須是檔案的根節點,且可包含一或多個 <item><group> 元素。
<item>
建立 MenuItem,代表選單中的單一項目。這個元素可包含巢狀 <menu> 元素,用來建立子選單。
<group>
用於 <item> 元素的選用隱藏容器。可以用來對選單項目進行分類,使其可以共用諸多屬性,例如活動狀態及瀏覽權限。詳情請參閱「建立選單群組」一節。

以下是名為 game_menu.xml 的選單範例:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/new_game"
          android:icon="@drawable/ic_new_game"
          android:title="@string/new_game"
          app:showAsAction="ifRoom"/>
    <item android:id="@+id/help"
          android:icon="@drawable/ic_help"
          android:title="@string/help" />
</menu>

<item> 元素支援多種屬性,可用來定義項目的外觀和行為。上述選單中的項目包含下列屬性:

android:id
該項目專屬的資源 ID,可讓應用程式在使用者選取時辨識該項目。
android:icon
可繪項目的參照,用來作為項目的圖示。
android:title
字串的參照,用來作為項目標題。
android:showAsAction
指出此項目在應用程式列顯示為操作項目的時間和方式規範。

這些是您使用的最重要的屬性,但還有更多屬性可用。如需所有支援的屬性的相關資訊,請參閱「選單資源」說明文件。

如要將子選單新增至任何選單中的項目,您可以新增 <menu> 元素做為 <item> 的子項。如果應用程式有許多功能可以依主題分類,例如電腦應用程式選單列中的項目 (例如「File」、「Edit」和「View」),就非常適合使用子選單。請參閱以下範例:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/file"
          android:title="@string/file" >
        <!-- "file" submenu -->
        <menu>
            <item android:id="@+id/create_new"
                  android:title="@string/create_new" />
            <item android:id="@+id/open"
                  android:title="@string/open" />
        </menu>
    </item>
</menu>

如要在活動中使用選單,請「inflate」選單資源,使用 MenuInflater.inflate() 將 XML 資源轉換為可編寫程式的物件。以下各節將說明如何為各種選單類型加載選單。

建立選項選單

選項選單 (如圖 1 所示) 可讓您加入與目前活動情境相關的操作和其他選項,例如「搜尋」、「撰寫電子郵件」和「設定」。

這張圖片顯示 Google 試算表應用程式的應用程式列
圖 2. Google 試算表應用程式,顯示了多個按鈕,包括動作溢位按鈕在內。

您可以從 Activity 子類別或 Fragment 子類別中宣告選項選單的項目。如果您的活動和片段都宣告了選項選單的項目,則這些項目會在 UI 中合併。活動的項目會先顯示,再按照片段加入活動的順序顯示每個片段的項目。如有需要,您可以在每個需要移動的 <item> 中使用 android:orderInCategory 屬性重新排序選單項目。

若要指定活動的選項選單,請覆寫 onCreateOptionsMenu()。片段會提供專屬的 onCreateOptionsMenu() 回呼。使用此方法時,您可以將選單資源 (以 XML 定義) 加載至回呼提供的 Menu 中。例如:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater: MenuInflater = menuInflater
    inflater.inflate(R.menu.game_menu, menu)
    return true
}

Java

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.game_menu, menu);
    return true;
}

您也可以使用 add() 新增選單項目,並使用 findItem() 擷取項目,透過 MenuItem API 修改其屬性。

處理點擊事件

當使用者從選項選單中選取項目 (包括應用程式列中的動作項目) 時,系統會呼叫活動的 onOptionsItemSelected() 方法。此方法會傳遞所選的 MenuItem。您可以藉由呼叫 getItemId() 識別該項目,這會回傳選單項目的專屬 ID,由選單資源中的 android:id 屬性定義,或是為 add() 方法指定的整數。您可以將此 ID 與已知的選單項目進行比對,以執行適當的動作。

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle item selection.
    return when (item.itemId) {
        R.id.new_game -> {
            newGame()
            true
        }
        R.id.help -> {
            showHelp()
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Java

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection.
    switch (item.getItemId()) {
        case R.id.new_game:
            newGame();
            return true;
        case R.id.help:
            showHelp();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

成功處理選單項目後,將 true 傳回。如果您不處理選單項目,請呼叫 onOptionsItemSelected() 的父類別實作。預設實作方式會傳回 false。

如果活動包含片段,系統會先針對活動呼叫 onOptionsItemSelected(),接著按照片段新增順序針對每個片段呼叫,直到一個傳回 true 或所有片段為止。

在執行階段變更選單項目

系統呼叫 onCreateOptionsMenu() 後,會保留您已填入的 Menu 執行個體,除非選單失效,否則不會再次呼叫 onCreateOptionsMenu()。不過,請只使用 onCreateOptionsMenu() 建立初始選單狀態,不要在活動生命週期期間進行變更。

如要根據活動生命週期期間發生的事件修改選項選單,您可以在 onPrepareOptionsMenu() 方法中執行操作。此方法會向您傳遞目前存在的 Menu 物件,因此您可以加以修改,例如新增、移除或停用項目。片段也會提供 onPrepareOptionsMenu() 回呼。

在應用程式列顯示選單項目時,選項選單會一律開啟。當事件發生且您想要執行選單更新時,請呼叫 invalidateOptionsMenu() 以要求系統呼叫 onPrepareOptionsMenu()

建立內容選單

顯示浮動內容選單的圖片
圖 3. 浮動內容選單。

內容選單可提供會影響 UI 中特定項目或內容畫面的動作。您可以為任何檢視畫面提供內容選單,但這些選單通常用於 RecylerView 中的項目或其他檢視畫面集合,方便使用者直接對各個項目執行操作。

提供內容關聯操作的方法有兩種:

  • 浮動內容選單中。當使用者的檢視畫面宣告支援內容選單時,選單就會以浮動式清單的方式顯示選單項目清單,與對話方塊類似。使用者一次可以對一個項目執行關聯操作。
  • 關聯動作模式中。這個模式是 ActionMode 的系統實作項目,會在畫面頂端顯示關聯動作列(CAB),並包含會影響所選項目的操作項目。啟用此模式時,如果應用程式支援這項功能,使用者就能一次對多個項目執行一項操作。

建立浮動內容選單

如要提供浮動內容選單,請執行下列步驟:

  1. 呼叫 registerForContextMenu() 並傳遞 View,註冊與內容選單相關聯的 View

    如果您的活動使用 RecyclerView,並您希望每個項目提供相同的內容選單,請將 RecyclerView 傳遞至 registerForContextMenu(),以註冊內容選單的所有項目。

  2. 在您的 ActivityFragment 中實作 onCreateContextMenu() 方法。

    當註冊的檢視畫面收到按住事件時,系統會呼叫 onCreateContextMenu() 方法。您可以在這個檔案定義選單項目,通常會透過加載選單資源的方式定義,如以下範例所示:

    Kotlin

        override fun onCreateContextMenu(menu: ContextMenu, v: View,
                                menuInfo: ContextMenu.ContextMenuInfo) {
            super.onCreateContextMenu(menu, v, menuInfo)
            val inflater: MenuInflater = menuInflater
            inflater.inflate(R.menu.context_menu, menu)
        }
        

    Java

        @Override
        public void onCreateContextMenu(ContextMenu menu, View v,
                                        ContextMenuInfo menuInfo) {
            super.onCreateContextMenu(menu, v, menuInfo);
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.context_menu, menu);
        }
        

    MenuInflater 可讓您從選單資源加載內容選單。回呼方法參數包括使用者選取的 View,以及可提供與選取項目相關額外資訊的 ContextMenu.ContextMenuInfo 物件。如果活動有多個檢視畫面,且每個檢視畫面提供不同的內容選單,您可以利用這些參數來判斷要加載哪些內容選單。

  3. 導入 onContextItemSelected(),如以下範例所示。當使用者選取選單項目時,系統會呼叫此方法,讓您執行適當的動作。

    Kotlin

        override fun onContextItemSelected(item: MenuItem): Boolean {
            val info = item.menuInfo as AdapterView.AdapterContextMenuInfo
            return when (item.itemId) {
                R.id.edit -> {
                    editNote(info.id)
                    true
                }
                R.id.delete -> {
                    deleteNote(info.id)
                    true
                }
                else -> super.onContextItemSelected(item)
            }
        }
        

    Java

        @Override
        public boolean onContextItemSelected(MenuItem item) {
            AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
            switch (item.getItemId()) {
                case R.id.edit:
                    editNote(info.id);
                    return true;
                case R.id.delete:
                    deleteNote(info.id);
                    return true;
                default:
                    return super.onContextItemSelected(item);
            }
        }
        

    getItemId() 方法會查詢所選選單項目的 ID,您可以使用 android:id 屬性以 XML 為每個選單項目進行指派,如 XML 中的選單所示。

    成功處理選單項目後,將 true 傳回。如果您不處理選單項目,請將選單項目傳遞至父類別實作。如果您的活動包含片段,活動會先收到此回呼。在未處理的情況下呼叫父類別時,系統會按照新增每個片段的順序,將事件傳遞至每個片段中相應的回呼方法,一次一個,直到傳回 truefalse 為止。Activityandroid.app.Fragment 的預設實作方式會傳回 false,因此在未處理時一律呼叫父類別。

使用關聯動作模式

關聯動作模式是 ActionMode 的系統實作,可將使用者互動專注於執行關聯動作。當使用者選取某個項目啟用此模式時,畫面頂端會出現關聯動作列,以顯示使用者可以對所選項目執行的操作。啟用此模式後,使用者就可以選取多個項目 (如果應用程式支援這項功能),還能取消選取項目並繼續在活動中瀏覽。當使用者取消選取所有項目、輕觸「返回」按鈕或輕觸列左側的「Done」動作時,操作模式即會停用,關聯動作列會消失。

針對提供內容關聯操作的檢視畫面,當發生下列兩種事件之一或同時發生時,您通常會叫用關聯動作模式:

  • 使用者按住檢視畫面。
  • 使用者在檢視畫面中選取核取方塊或類似的 UI 元件。

視您的設計而定,應用程式如何叫用關聯動作模式,並定義每個動作的行為。共有兩種設計:

  • 用於個別任意檢視畫面的內容關聯操作。
  • 對於 RecyclerView 中的項目群組進行批次關聯操作,讓使用者可以選取多個項目,並對所有項目執行動作。

以下章節介紹了各個情境所需的設定。

為個別檢視畫面啟用關聯動作模式

如果只想在使用者選取特定檢視畫面時叫用關聯動作模式,請執行下列步驟:

  1. 導入 ActionMode.Callback 介面,如以下範例所示。在回呼方法中,您可以指定關聯動作列的操作、回應操作項目的點擊事件,以及為動作模式處理其他生命週期事件。

    Kotlin

        private val actionModeCallback = object : ActionMode.Callback {
            // Called when the action mode is created. startActionMode() is called.
            override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
                // Inflate a menu resource providing context menu items.
                val inflater: MenuInflater = mode.menuInflater
                inflater.inflate(R.menu.context_menu, menu)
                return true
            }
    
            // Called each time the action mode is shown. Always called after
            // onCreateActionMode, and might be called multiple times if the mode
            // is invalidated.
            override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
                return false // Return false if nothing is done
            }
    
            // Called when the user selects a contextual menu item.
            override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
                return when (item.itemId) {
                    R.id.menu_share -> {
                        shareCurrentItem()
                        mode.finish() // Action picked, so close the CAB.
                        true
                    }
                    else -> false
                }
            }
    
            // Called when the user exits the action mode.
            override fun onDestroyActionMode(mode: ActionMode) {
                actionMode = null
            }
        }
        

    Java

        private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
    
            // Called when the action mode is created. startActionMode() is called.
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // Inflate a menu resource providing context menu items.
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.context_menu, menu);
                return true;
            }
    
            // Called each time the action mode is shown. Always called after
            // onCreateActionMode, and might be called multiple times if the mode
            // is invalidated.
            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false; // Return false if nothing is done.
            }
    
            // Called when the user selects a contextual menu item.
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
               switch (item.getItemId()) {
                    case R.id.menu_share:
                        shareCurrentItem();
                        mode.finish(); // Action picked, so close the CAB.
                        return true;
                    default:
                        return false;
                }
            }
    
            // Called when the user exits the action mode.
            @Override
            public void onDestroyActionMode(ActionMode mode) {
                actionMode = null;
            }
        };
        

    這些事件回呼與選項選單中的回呼幾乎相同,唯每個回呼也會傳遞與事件相關的 ActionMode 物件。您可以使用 ActionMode API 對 CAB 進行多項變更,例如利用 setTitle()setSubtitle() 修改標題和子標題,這有助於指出已選取的項目數量。

    上述範例會在刪除動作模式時,將 actionMode 變數設為 null。下一個步驟將說明初始化方式,以及如何在活動或片段中儲存成員變數。

  2. 如要在顯示長條時 (例如使用者按住檢視畫面時),請呼叫 startActionMode()

    Kotlin

        someView.setOnLongClickListener { view ->
            // Called when the user performs a touch & hold on someView.
            when (actionMode) {
                null -> {
                    // Start the CAB using the ActionMode.Callback defined earlier.
                    actionMode = activity?.startActionMode(actionModeCallback)
                    view.isSelected = true
                    true
                }
                else -> false
            }
        }
        

    Java

        someView.setOnLongClickListener(new View.OnLongClickListener() {
            // Called when the user performs a touch & hold on someView.
            public boolean onLongClick(View view) {
                if (actionMode != null) {
                    return false;
                }
    
                // Start the CAB using the ActionMode.Callback defined earlier.
                actionMode = getActivity().startActionMode(actionModeCallback);
                view.setSelected(true);
                return true;
            }
        });
        

    當您呼叫 startActionMode() 時,系統會傳回建立的 ActionMode。將此項目儲存至成員變數中,即可變更關聯動作列以回應其他事件。在上述範例中,ActionMode 是用來確保在活動期間不會重新建立 ActionMode 執行個體,方法是先檢查成員是否為空值,接著再啟動動作模式。

建立彈出式選單

這張圖片顯示 Gmail 應用程式中的彈出式選單,並固定在右上方的溢位按鈕上。
圖 4. Gmail 應用程式中的彈出式選單,固定在右上角的溢位按鈕上。

PopupMenu 是固定在 View 上的強制回應選單。如果有空間,它會顯示在錨定檢視畫面下方,或者顯示在檢視畫面上方。這項功能非常實用:

  • 為與特定內容 (例如圖 4 中顯示的 Gmail 電子郵件標頭) 相關的操作提供溢位樣式選單。
  • 提供指令句的第二部分,例如標示「Add」的按鈕,可產生包含不同「Add」選項的彈出式選單。
  • 提供與 Spinner 類似,但不保留永久選項的選單。

如果您以 XML 定義選單,可以按照下列步驟顯示彈出式選單:

  1. 利用其建構函式將 PopupMenu 執行個體化,此操作會將目前應用程式的 ContextView 帶到選單錨定的地方。
  2. 使用 MenuInflater 將選單資源加載至 PopupMenu.getMenu() 傳回的 Menu 物件。
  3. 呼叫 PopupMenu.show()

例如,以下是顯示彈出式選單的按鈕:

<ImageButton
    android:id="@+id/dropdown_menu"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:contentDescription="@string/descr_overflow_button"
    android:src="@drawable/arrow_drop_down" />

這項活動隨即會顯示如下的彈出式選單:

Kotlin

findViewById<ImageButton>(R.id.dropdown_menu).setOnClickListener {
    val popup = PopupMenu(this, it)
    val inflater: MenuInflater = popup.menuInflater
    inflater.inflate(R.menu.actions, popup.menu)
    popup.show()
}

Java

findViewById(R.id.dropdown_menu).setOnClickListener(v -> {
    PopupMenu popup = new PopupMenu(this, v);
    popup.getMenuInflater().inflate(R.menu.actions, popup.getMenu());
    popup.show();
});

當使用者選取項目或輕觸選單區域外時,選單會關閉。您可以使用 PopupMenu.OnDismissListener 監聽關閉事件。

處理點擊事件

如要在使用者選取選單項目時執行動作,請實作 PopupMenu.OnMenuItemClickListener 介面,並呼叫 setOnMenuItemclickListener() 以向 PopupMenu 註冊。當使用者選取某個項目時,系統會在介面中呼叫 onMenuItemClick() 回呼。

例如:

Kotlin

fun showMenu(v: View) {
    PopupMenu(this, v).apply {
        // MainActivity implements OnMenuItemClickListener.
        setOnMenuItemClickListener(this@MainActivity)
        inflate(R.menu.actions)
        show()
    }
}

override fun onMenuItemClick(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.archive -> {
            archive(item)
            true
        }
        R.id.delete -> {
            delete(item)
            true
        }
        else -> false
    }
}

Java

public void showMenu(View v) {
    PopupMenu popup = new PopupMenu(this, v);

    // This activity implements OnMenuItemClickListener.
    popup.setOnMenuItemClickListener(this);
    popup.inflate(R.menu.actions);
    popup.show();
}

@Override
public boolean onMenuItemClick(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.archive:
            archive(item);
            return true;
        case R.id.delete:
            delete(item);
            return true;
        default:
            return false;
    }
}

建立菜單群組

選單群組是指一組共用特定特色的選單項目集合。您可以透過群組執行以下操作:

您可以在選單資源中的 <group> 元素內建立巢狀結構 <item> 元素,以此建立一個群組,或使用 add() 方法指定群組 ID。

以下是含有群組的選單資源範例:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_save"
          android:icon="@drawable/menu_save"
          android:title="@string/menu_save" />
    <!-- menu group -->
    <group android:id="@+id/group_delete">
        <item android:id="@+id/menu_archive"
              android:title="@string/menu_archive" />
        <item android:id="@+id/menu_delete"
              android:title="@string/menu_delete" />
    </group>
</menu>

群組中的項目會與第一個項目顯示同一級別,選單中所有三個項目均為同層級。不過,您可以參照群組 ID 並使用上述方法,修改群組中兩個項目的特徵。系統也絕不會分割群組的項目。舉例來說,如果您為每個項目宣告 android:showAsAction="ifRoom",這兩者都會顯示在動作列中,或同時顯示在溢位操作中。

使用可勾選的選單項目

圖 5.包含可勾選項目的子選單。

選單對於開啟和關閉選項來說是很實用的介面,針對獨立選項使用核取方塊,而互斥選項的群組則可使用圓形按鈕。圖 5 顯示子選單,其中包含可使用圓形按鈕勾選的項目。

您可以使用 <item> 元素中的 android:checkable 屬性定義個別選單項目的可核取行為,或是在 <group> 元素中使用 android:checkableBehavior 屬性為整個群組定義。舉例來說,這個選單群組中的所有項目均可使用圓形按鈕勾選:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <item android:id="@+id/red"
              android:title="@string/red" />
        <item android:id="@+id/blue"
              android:title="@string/blue" />
    </group>
</menu>

android:checkableBehavior 屬性接受下列其中一項:

single
只能勾選群組中的一個項目,因此會顯示圓形按鈕。
all
所有項目均可勾選,因此會勾選核取方塊。
none
沒有項目可供勾選。

您可以透過 <item> 元素中的 android:checked 屬性,對某個項目套用預設的勾選狀態,然後使用 setChecked() 方法在程式碼中進行變更。

選取可勾選項目時,系統會呼叫所選項目的個別回呼方法,例如 onOptionsItemSelected()。您可以在這個步驟設定核取方塊狀態,因為核取方塊或圓形按鈕不會自動變更狀態。您可以使用 isChecked() 查詢項目目前的狀態 (如同使用者選取前的狀態),然後使用 setChecked() 將其狀態設定為已勾選。如以下範例所示:

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.vibrate, R.id.dont_vibrate -> {
            item.isChecked = !item.isChecked
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Java

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.vibrate:
        case R.id.dont_vibrate:
            if (item.isChecked()) item.setChecked(false);
            else item.setChecked(true);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

如果您未以這種方式設定勾選狀態,則使用者選取核取方塊或圓形按鈕時,其顯示狀態不會改變。若您設定了狀態,活動會保留該項目的勾選狀態,因此當使用者之後開啟選單時,就可以看到您設定的已勾選狀態。

根據意圖新增選單項目

有時,您會希望選單項目使用 Intent 啟動活動 (無論是您的應用程式或其他應用程式中的活動)。如果您知道要使用的意圖,且具有可啟動意圖的特定選單項目,就可以在適當的選取項目回呼方法中,使用 startActivity() 執行意圖,例如 onOptionsItemSelected() 回呼。

然而,如果您不確定使用者裝置是否含有會處理意圖的應用程式,那麼新增會叫用該意圖的選單項目,可能會導致選單項目無法運作,因為該意圖可能無法解析活動。為解決這個問題,當 Android 在處理您的意圖的裝置上找到活動時,您可透過動態的方式將選單項目加入選單。

如要根據接受意圖的可用活動新增選單項目,請執行下列步驟:

  1. 定義含有 CATEGORY_ALTERNATIVECATEGORY_SELECTED_ALTERNATIVE 類別或兩者並加上任何其他要求的意圖。
  2. 呼叫 Menu.addIntentOptions()。Android 會搜尋任何可執行該意圖的應用程式,並將其加入選單。

如果沒有安裝任何符合意圖的應用程式,系統就不會新增選單項目。

例如:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    super.onCreateOptionsMenu(menu)

    // Create an Intent that describes the requirements to fulfill, to be
    // included in the menu. The offering app must include a category value
    // of Intent.CATEGORY_ALTERNATIVE.
    val intent = Intent(null, dataUri).apply {
        addCategory(Intent.CATEGORY_ALTERNATIVE)
    }

    // Search and populate the menu with acceptable offering apps.
    menu.addIntentOptions(
            R.id.intent_group,  // Menu group to which new items are added.
            0,                  // Unique item ID (none).
            0,                  // Order for the items (none).
            this.componentName, // The current activity name.
            null,               // Specific items to place first (none).
            intent,             // Intent created above that describes the requirements.
            0,                  // Additional flags to control items (none).
            null)               // Array of MenuItems that correlate to specific items (none).

    return true
}

Java

@Override
public boolean onCreateOptionsMenu(Menu menu){
    super.onCreateOptionsMenu(menu);

    // Create an Intent that describes the requirements to fulfill, to be
    // included in the menu. The offering app must include a category value
    // of Intent.CATEGORY_ALTERNATIVE.
    Intent intent = new Intent(null, dataUri);
    intent.addCategory(Intent.CATEGORY_ALTERNATIVE);

    // Search and populate the menu with acceptable offering apps.
    menu.addIntentOptions(
         R.id.intent_group,         // Menu group to which new items are added.
         0,                         // Unique item ID (none).
         0,                         // Order for the items (none).
         this.getComponentName(),   // The current activity name.
         null,                      // Specific items to place first (none).
         intent,                    // Intent created above that describes the requirements.
         0,                         // Additional flags to control items (none).
         null);                     // Array of MenuItems that correlate to specific items (none).

    return true;
}

系統會找到提供意圖篩選器並符合所定義意圖的每個活動,並為其新增選單項目,以意圖篩選器的 android:label 值做為選單項目標題,並以應用程式圖示作為選單項目圖示。addIntentOptions() 方法會傳回新增的選單項目數量。

將活動新增至其他選單

您可以向其他應用程式提供活動服務,讓應用程式能夠納入其他應用程式的選單中,亦即取消先前所述的角色。

若要加至其他應用程式的選單中,請照常定義意圖篩選器,但加入 CATEGORY_ALTERNATIVE 和/或 CATEGORY_SELECTED_ALTERNATIVE 值的意圖篩選器類別。例如:

<intent-filter label="@string/resize_image">
    ...
    <category android:name="android.intent.category.ALTERNATIVE" />
    <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    ...
</intent-filter>

如要進一步瞭解如何編寫意圖篩選器,請參閱意圖和意圖篩選器