Skip to content

Most visited

Recently visited

navigation

選單

選單在許多類型的應用程式中都是常見的使用者介面元件。為提供熟悉且一致的使用者體驗,您應該使用 Menu API 來呈現 Activity 中的使用者動作與其他選項。

從 Android 3.0 (API 級別 11) 開始,提供 Android 的裝置不再需要提供專屬的「選單」按鈕。 有此變更之後,Android 應用程式應可脫離對傳統有 6 個項目的選單面板的依賴,改為提供動作列來呈現一般的使用者動作。

雖然有些選單項目的設計與使用者體驗有所變更,但依然是根據 Menu API 來定義一組動作與選項的語意。本指南說明如何在所有版本的 Android 上,建立三個基本類型的選單或動作呈現方式:

選項選單和動作列
選項選單是 Activity 的主要選單項目集合。 您應該將對應用程式有全域影響的動作放置在此,例如「搜尋」、「撰寫電子郵件」及「設定」。

如果您是為 Android 2.3 以下版本進行開發,使用者可按下「選單」按鈕來顯示選項選單面板。

在 Android 3.0 以上版本,選項選單的項目是當成螢幕上的動作項目與溢出選項組合,以動作列呈現。 從 Android 3.0 開始,「選單」按鈕已淘汰 (有些裝置甚至沒有),因此您應轉向使用動作列來存取動作和其他選項。

請參閱建立選項選單

內容選單和內容關聯動作模式
內容選單是會在使用者長按某元素時顯示的浮動選單。 它提供的動作會影響所選取內容或內容畫面。

針對 Android 3.0 以上版本進行開發時,您應該改為使用關聯比對動作模式,以啟用所選取內容的動作。此模式顯示的動作項目會影響畫面頂端列中選取的內容,並允許使用者選取多個項目。

請參閱建立內容關聯選單

彈出式選單
彈出式選單顯示的項目清單會以垂直清單的方式,錨定在呼叫該選單的檢視。 它很適合用來提供與特定內容有關的動作溢出,或針對第二部分的命令提供選項。 彈出式選單中的動作「不」應直接影響對應內容,應由內容關聯動作直接影響。 彈出式選單主要用於您 Activity 中與內容區域相關的延伸動作。

請參閱建立彈出式選單

在 XML 中定義選單

對於所有選單類型,Android 提供標準 XML 格式來定義選單項目。 您應該在 XML 選單資源中定義選單與其相關項目,而不是在您 Activity 的程式碼中建置選單。 接著,您可以擴大 Activity 或片段中的選單資源 (當成 Menu 物件載入)。

建議使用選單資源的幾個理由如下:

如要定義選單,可在專案的 res/menu/ 目錄內建立 XML 檔案,然後利用下列元素建置選單:

<menu>
定義選單項目的容器 Menu<menu> 元素必須是檔案的根節點,並可保留一或多個 <item><group> 元素。
<item>
建立代表選單中單一項目的 MenuItem。此元素可以包含巢狀 <menu> 元素以建立子選單。
<group>
可供 &lt;item&gt; 元素選用的不可見容器。它可讓您將選單項目分類,以便分享屬性,例如有效狀態與可見度。 如需詳細資訊,請參閱建立選單群組

稱為 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"
          android: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
指定此項目應何時且如何顯示為動作列中的動作項目。

這些都是您應該使用的最重要屬性,但不侷限於上述這幾個。 如需所有支援屬性的詳細資訊,請參閱選單資源

您可以藉由將 &lt;menu&gt; 元素新增為 &lt;item&gt; 的子項,將子選單新增至任何選單 (子選單除外) 的項目。 當您的應用程式有很多可按主題分類的功能,例如 PC 應用程式選單列中的項目 (檔案、編輯、檢視等等) 時,子選單相當有用。 例如:

<?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>

如要在 Activity 中使用選單,您必須使用 MenuInflater.inflate() 擴大選單資源 (將 XML 轉換成可程式化的物件)。 下列各節將說明如何擴大各種 選單類型的選單。

建立選項選單

圖 1.Android 2.3 裝置上瀏覽器中的選項選單。

您應該在選項選單中包括與目前 Activity 內容關聯動作和其他選項,例如「搜尋」、「撰寫電子郵件」及「設定」。

選項選單中的項目會顯示在螢幕上的哪個位置,取決於您為其開發應用程式的版本。

圖 2.Honeycomb 圖片庫應用程式的動作列,顯示導覽索引標籤與相機動作項目 (再加上動作溢出按鈕)。

您可以從 Activity 子類別或 Fragment 子類別宣告選項選單的項目。 如果您的 Activity 與片段都宣告選項選單的項目,兩者會在 UI 中結合。 先顯示 Activity 的項目,接著會依片段新增至 Activity 的順序顯示各片段的項目。 您可以視需要在您想移動的 &lt;item&gt; 中,利用其 android:orderInCategory屬性重新排列選單項目的順序。

如要指定 Activity 的選項選單,可覆寫 onCreateOptionsMenu() (片段會提供自己的 onCreateOptionsMenu() 回呼)。在這種方法中,您可以將選單資源(在 XML 中完成定義) 擴大回呼中提供的 Menu。 例如:

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

透過 MenuItem API,您也可以使用 add() 來新增選單項目,以及利用 findItem() 擷取項目來修訂它們的屬性。

如果您是為 Android 2.3.x 以下版本開發應用程式,當使用者初次開啟選單時,系統會呼叫 onCreateOptionsMenu(),以建立選項選單。 如果您是為 Android 3.0 以上版本開發應用程式,啟動 Activity 時,系統會呼叫 onCreateOptionsMenu(),以在動作列顯示項目。

處理點擊事件

使用者從選項選單 (包括動作列中的動作項目) 中選取項目時,系統會呼叫您 Activity 的 onOptionsItemSelected() 方法。此方法會傳送所選取的 MenuItem。您可以呼叫 getItemId() 傳回選單項目的唯一 ID (由選單資源中的 android:id 屬性或透過指定給 add() 方法的整數來定義) 來識別該項目。您可以將此 ID 和已知選單項目比對,以執行適當動作。 例如:

@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)。

如果您的 Activity 包含片段,系統會先呼叫 Activity 的 onOptionsItemSelected(),再依片段的新增順序呼叫各片段,直到其中之一傳回 true 或所有片段均已呼叫。

提示:Android 3.0 新增的功能可讓您在 XML 中使用 android:onClick 屬性定義選單項目的點擊行為。該屬性值必須是使用選單的 Activity 所定義的方法名稱。 它必須是公用方法且接受單一 MenuItem 參數,當系統呼叫此方法時,它會傳送選取的選單項目。 如需詳細資訊與範例,請參閱選單資源文件。

提示:如果您的應用程式包含多個 Activity 且有一些提供相同的選項選單,可考慮建立只實作 onCreateOptionsMenu()onOptionsItemSelected() 方法的 Activity。 接著,針對應共用相同選項選單的 Activity 擴充此類別。 如此一來,您可以管理一組處理選單動作的程式碼,以及每一個繼承選單行為的子系類別。 如果您想要將選單項目新增至其中一個子系 Activity,請覆寫該 Activity 中的 onCreateOptionsMenu()。呼叫 super.onCreateOptionsMenu(menu) 以建立原始的選單項目,然後利用 menu.add() 來新增選單項目。您也可以覆寫個別選單項目的超級類別行為。

在執行階段變更選單項目

系統呼叫 onCreateOptionsMenu() 之後,會保留您填入的 Menu 執行個體,除非該選單因某種理由而變無效,否則不會再次呼叫 onCreateOptionsMenu()。 不過,onCreateOptionsMenu() 應該只用來建立初始選單狀態,您不要在 Activity 生命週期間用來進行變更。

如果您想要根據 Activity 生命週期當中發生的事件來修改選項選單,您可以使用 onPrepareOptionsMenu() 方法這麼做。 這個方法會將目前存在的 Menu 物件傳送給您加以修改,例如新增、移除或停用項目 (片段也會提供 onPrepareOptionsMenu() 回呼)。

在 Android 2.3.x 以下版本,每當使用者開啟選項選單 (按下 [選單] 按鈕) 時,系統都會呼叫 onPrepareOptionsMenu()

在 Android 3.0 以上版本,當選單項目顯示在動作列時會一律將選項選單視為開啟。 當事件發生且您想要執行選單更新時,您必須呼叫 invalidateOptionsMenu(),以要求系統呼叫 onPrepareOptionsMenu()

注意:您不應該根據目前處於焦點狀態的 View,變更選項選單中的項目。 處於輕觸模式 (使用者未使用軌跡球或導覽用的方向鍵) 時,檢視無法成為焦點,因此您不應該使用焦點當成修改選項選單中項目時的依據。 如果您想要在 View 提供具內容相關性的選單項目,請使用內容選單

建立內容關聯選單

圖 3.浮動內容選單的螢幕擷取畫面 (左) 與內容關聯動作列 (右)。

內容關聯選單提供的動作會影響 UI 中的特定項或內容畫面。 您可以為任何檢視提供內容選單,但它們通常用於使用者能直接對各項目執行動作的 ListViewGridView 或其他檢視集合中的項目。

您有兩種方式可提供內容關聯動作:

注意:Android 3.0 (API 級別 11) 以上版本可以使用內容關聯動作模式,此模式同時是可以顯示內容關聯動作時的偏好技術。 如果您的應用程式支援 3.0 以下版本,您應該在這類裝置上切換為浮動內容選單。

建立浮動內容選單

如何提供浮動內容選單:

  1. 呼叫 registerForContextMenu() 並將 View 傳送給它,向應該建立關聯的內容選單註冊 View

    如果您的 Activity 使用 ListViewGridView,且您希望每個項目都提供相同的內容選單,可將 ListViewGridView 傳送至 registerForContextMenu() 來註冊內容選單的所有項目。

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

    當註冊的檢視收到長按事件時,系統會呼叫 onCreateContextMenu() 方法。 您可以在這裡定義選單項目,方法通常是擴大選單資源。例如:

    @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 物件。 如果 Activity 有數個分別提供不同內容選單的檢視,您可以使用這些參數來決定要擴大的內容選單。

  3. 實作 onContextItemSelected()

    當使用者選取選單項目時,系統會呼叫此方法,以便您執行適當的動作。 例如:

    @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。如果您不處理選單項目,請將選單項目傳送至超級類別實作。 如果您的 Activity 包括片段,該 Activity 會先收到此回呼。 在不處理時呼叫超級類別,系統就可以一次一個 (依片段的新增順序) 將事件傳送至各片段中的個別回呼方法,直到傳回 truefalse。 ( Activityandroid.app.Fragment 的預設實作會傳回 false,因此當您不處理時,務必要呼叫超級類別。)

使用內容關聯動作模式

內容關聯動作模式是 ActionMode 的系統實作,執行內容關聯動作時著重於與使用者互動。 當使用者選取項目而啟用此模式時,「內容關聯動作列」會出現在畫面頂端,呈現使用者可在目前所選項目上執行的動作。 此模式啟用時,使用者能選取多個項目 (如果您允許的話)、取消選取項目,還可以在 Activity 內繼續瀏覽 (在您允許的範圍內)。 當使用者取消選取所有項目、按下 [後退] 按鈕,或選取該列左側的[完成] 按鈕時,動作模式會停用且內容 關聯 動作列也會消失。

注意:內容關聯動作列不一定要與動作列關聯。 即使內容相關動作列在視覺上覆蓋動作列的位置,兩者依然獨立運作。

如果您在為 Android 3.0 (API 級別 11) 以上版本進行開發,您應使用內容關聯動作模式來呈現內容動作,而不是浮動內容選單

針對提供內容相關動作的檢視,您應該就下列兩種事件之一 (或兩者) 呼叫內容關聯動作模式:

應用程式如何呼叫內容關聯動作模式以及如何定義每個動作的行為,視您的設計而定。 基本上可分為兩種設計:

下列各節說明每種情況所需的設定。

為個別的檢視啟用內容關離動作模式

如果您只有在使用者選取特定檢視時,才想要呼叫內容關聯動作模式,建議您採取以下動作:

  1. 實作 ActionMode.Callback 介面。在它的回呼方法中,您可以指定內容相關動作列的動作、回應動作項目的點擊事件,以及處理動作模式的其他生命週期事件。
  2. 當您想要顯示該列時 (例如當使用者長按檢視時),可呼叫 startActionMode()

例如:

  1. 實作 ActionMode.Callback 介面:
    private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
    
        // Called when the action mode is created; startActionMode() was 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, but
        // may 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) {
            mActionMode = null;
        }
    };
    

    請注意,這些事件回呼幾乎和選項選單的回呼一模一樣,只是每一個都會傳送與事件關聯的 ActionMode 物件。您可以使用 ActionMode API 對 CAB 進行各種變更,例如使用 setTitle()setSubtitle() 修改標題與子標題 (指出已選取的項目數量相當有用)。

    同時請注意,當動作模式終結時,上述範例會將 mActionMode 變數設為 null。 在下個步驟中,您將看到它是如何初始化,以及如何儲存 Activity 或片段中的成員變數,非常實用。

  2. 呼叫 startActionMode() (可以的話) 以啟用內容關聯動作模式,例如回應長按 View

    someView.setOnLongClickListener(new View.OnLongClickListener() {
        // Called when the user long-clicks on someView
        public boolean onLongClick(View view) {
            if (mActionMode != null) {
                return false;
            }
    
            // Start the CAB using the ActionMode.Callback defined above
            mActionMode = getActivity().startActionMode(mActionModeCallback);
            view.setSelected(true);
            return true;
        }
    });
    

    當您呼叫 startActionMode() 時,系統會傳回建立的 ActionMode。只要將此儲存在成員變數中,您就可以變更內容關聯動作列以回應其他事件。 在上述範例中, ActionMode 是用來確保不會重新建立已在使用中的 ActionMode 執行個體,方法是在將動作模式啟動之前,檢查成員是否為 null。

啟用 ListView 或 GridView 中的批次內容相關動作

如果您在 ListViewGridView (或 AbsListView 的另一個延伸) 中有一系列項目,且想要允許使用者執行批次動作,請進行以下動作:

例如:

ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position,
                                          long id, boolean checked) {
        // Here you can do something when items are selected/de-selected,
        // such as update the title in the CAB
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        // Respond to clicks on the actions in the CAB
        switch (item.getItemId()) {
            case R.id.menu_delete:
                deleteSelectedItems();
                mode.finish(); // Action picked, so close the CAB
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate the menu for the CAB
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.context, menu);
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        // Here you can make any necessary updates to the activity when
        // the CAB is removed. By default, selected items are deselected/unchecked.
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        // Here you can perform updates to the CAB due to
        // an invalidate() request
        return false;
    }
});

這樣一來,當使用者以長按的方式選取項目時,系統就會呼叫 onCreateActionMode() 方法,並顯示包含指定動作的內容相關動作列。可以看見內容關聯動作列時,使用者即可選取其他項目。

在某些情況下,內容關聯動作提供一般動作項目,因為使用者可能未發現有長按行為,所以您可能希望新增核取方塊或類似的 UI 元素,讓他們選取項目。 當使用者選取核取方塊時,您可以使用 setItemChecked() 將個別的清單項目設定成已核取狀態,以呼叫內容關聯動作模式。

建立彈出式選單

圖 4.Gmail 應用程式中的彈出式選單錨定於右上角的溢出按鈕。

PopupMenu 是錨定於 View 的強制回應選單。 有空間的畫會顯示在錨定檢視下方或檢視上方。適合用途:

注意: API 級別 11 以上版本才可以使用 PopupMenu

如果您在 XML 中定義選單,以下說明如何顯示彈出式選單:

  1. 透過其建構函式將 PopupMenu 具現化,使用應錨定選單的目前應用程式 ContextView
  2. 使用 MenuInflater 將您的選單資源擴大成 PopupMenu.getMenu() 所傳回的 Menu 物件。針對 14 以上的 API 級別,您可以改用 PopupMenu.inflate()
  3. 呼叫 PopupMenu.show()

例如,以下是含有 android:onClick 屬性可顯示彈出式選單的按鈕。

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_overflow_holo_dark"
    android:contentDescription="@string/descr_overflow_button"
    android:onClick="showPopup" />

接著,該 Activity 可以顯示彈出式選單,如下所示:

public void showPopup(View v) {
    PopupMenu popup = new PopupMenu(this, v);
    MenuInflater inflater = popup.getMenuInflater();
    inflater.inflate(R.menu.actions, popup.getMenu());
    popup.show();
}

在 14 以上的 API 級別中,您可以利用 PopupMenu.inflate() 將兩行結合來擴大選單。

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

處理點擊事件

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

例如:

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

建立選單群組

選單群組是指某些特性相同的選單項目集合。您可以利用群組:

您可以將 &lt;item&gt; 元素堆疊在選單資源中的 &lt;group&gt;元素內,或使用 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 顯示的子選單包含能以圓形按鈕勾選的項目。

注意:圖示選單 (出自選項選單) 中的選單項目無法顯示核取方塊或選項按鈕。 如果您選擇要將圖示選單中的項目設為可勾選,每當狀態變更時,您都必須切換圖示和/或文字,手動指出勾選狀態。

您可以使用 &lt;item&gt; 元素中的 android:checkable 屬性,為個別的選單項目定義可勾選行為,或利用 &lt;group&gt; 元素中的 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
沒有任何項目可供勾選

您可以使用 &lt;item&gt; 元素中的 android:checked 屬性將預設的勾選狀態套用至項目,並使用 setChecked() 方法在程式碼中變更它。

已選取可勾選項目時,系統會呼叫所選取個別項目的回呼方法 (例如 onOptionsItemSelected())。 您必須在這裡設定核取方塊的狀態,原因是核取方塊或選項按鈕並不會自動變更其狀態。 您可以利用 isChecked() 來查詢項目的目前狀態 (使用者選取它之前的狀態),然後利用 setChecked() 來設定勾選狀態。例如:

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

如果您不以這種方式設定已勾選狀態,將無法在使用者選取時變更項目 (核取方塊或選項按鈕) 的可見狀態。 當您確實設定狀態,Activity 會保留項目的已勾選狀態,當使用者稍後開啟選單時,即可看見您設定的已勾選狀態。

注意:可勾選的選單項目只能在各工作階段上使用,並不會在應用程式終結後儲存。 如果想為使用者儲存特定應用程式設定,請使用共用偏好設定

根據意圖新增選單項目

有時候您會希望選單項目使用 Intent來啟動 Activity (不論是您的應用程式或另一應用程式中的 Activity)。 當您知道想要使用的意圖,同時有應繼承該意圖的特定選單項目時,您可在使用者選取項目時才回呼的適當方法實作期間使用 startActivity() 執行該意圖 (例如 onOptionsItemSelected() callback) 回呼)。

不過,如果您不確定使用者的裝置是否包含可處理該意圖的應用程式,而新增可呼叫它的選單項目會導致選單項目無法運作,原因可能是該意圖不會解析成 Activity。 為解決這個問題,當 Android 在處理您意圖的裝置上找到 Activity 時,Android 會讓您將選單項目動態新增至選單。

如何根據接受意圖的可用 Activity 來新增選單項目:

  1. 定義類別為 CATEGORY_ALTERNATIVE 和/或 CATEGORY_SELECTED_ALTERNATIVE 的意圖,再加上其他需求。
  2. 呼叫 Menu.addIntentOptions()。Android 接著會搜尋可執行該意圖的任何應用程式,並將其新增至您的選單。

如果未安裝可滿足該意圖的應用程式,則不會新增任何選單項目。

注意: CATEGORY_SELECTED_ALTERNATIVE 是用來處理畫面上目前選取的元素。 因此,請只在 onCreateContextMenu() 中建立選單的情況下才使用。

例如:

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

    // Create an Intent that describes the requirements to fulfill, to be included
    // in our 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 applications.
    menu.addIntentOptions(
         R.id.intent_group,  // Menu group to which new items will be 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 our requirements
         0,      // Additional flags to control items (none)
         null);  // Array of MenuItems that correlate to specific items (none)

    return true;
}

找到的各個 Activity 提供的意圖篩選器如果與定義的意圖相符,就會新增選單項目,使用意圖篩選器的 android:label 中的值當成選單項目標題,並將應用程式圖示當成選單項目圖示。 此外, addIntentOptions() 方法還會傳回新增的選單項目數量。

注意:當您呼叫 addIntentOptions() 時,它會覆寫第一個引數中所指定選單群組中的任何或所有選單項目。

允許將 Activity 新增至其他選單

您也能向其他應用程式提供 Activity 的服務,這樣即可在其他應用程式的選單中包含您的應用程式 (與上述的角色顛倒)。

如要包含在其他應用程式選單中,您必須照常定義意圖篩選器,但務必為意圖篩選器類別納入 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>

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

如需採用此技術的範例應用程式,請參閱 NotePad 範例程式碼。

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)