新增菜單

試用 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 的系統實作,可將重點放在使用者互動以執行關聯動作。當使用者選取項目啟用此模式時,畫面頂端會顯示關聯動作列,顯示使用者可對所選項目執行的動作。啟用此模式時,使用者可以選取多個項目 (如果應用程式支援該功能),並可取消選取項目,並繼續在活動中瀏覽。如果使用者取消選取所有項目、輕觸「返回」按鈕,或輕觸列左側的「完成」動作,動作模式就會停用,關聯動作列也會消失。

如果是提供關聯動作的檢視畫面,通常只有在這兩個事件發生以下一或兩個事件時,您通常會叫用關聯動作模式:

  • 當使用者按住檢視畫面。
  • 使用者在檢視畫面中選取核取方塊或類似的 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 的強制回應選單。如果有空間,它會顯示在錨定檢視畫面下方,或者顯示在檢視畫面上方。這項工具適用於下列作業:

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

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

  1. 使用其建構函式將 PopupMenu 例項化,該建構函式會取用目前應用程式 Context 和選單固定位置的 View
  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 啟動活動。如果您知道要使用的意圖,且有一個用來啟動意圖的特定選單項目,可以在適當的項目選取回呼方法 (例如 onOptionsItemSelected() 回呼) 中使用 startActivity() 執行意圖。

然而,如果您不確定使用者裝置是否包含會處理意圖的應用程式,那麼新增叫用該意圖的選單項目可能會導致選單項目無法運作,因為該意圖可能無法解析活動。為解決這個問題,當 Android 在處理意圖的裝置上找到活動時,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_ALTERNATIVECATEGORY_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>

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