Android官方文檔—User Interface(Menus)

菜單

菜單是許多類型的應用程序中的常見用戶界面組件。要提供熟悉且一致的用戶體驗,您應使用菜單API在活動中顯示用戶操作和其他選項。

從Android 3.0(API級別11)開始,不再需要Android驅動的設備來提供專用的菜單按鈕。通過此更改,Android應用程序應遠離對傳統的6項菜單面板的依賴,而是提供應用欄以顯示常見的用戶操作。

儘管某些菜單項的設計和用戶體驗已發生變化,但定義一組操作和選項的語義仍基於Menu API。本指南介紹如何在所有Android版本上創建三種基本類型的菜單或操作演示:

選項菜單和應用欄

選項菜單是活動的主菜單項集合。您應該在此處放置對應用程序具有全局影響的操作,例如“搜索”,“撰寫電子郵件”和“設置”。

請參閱有關創建選項菜單的部分。

上下文菜單和上下文操作模式

上下文菜單是當用戶對元素執行長按時顯示的浮動菜單。它提供影響所選內容或上下文框架的操作。

上下文操作模式顯示影響屏幕頂部欄中所選內容的操作項,並允許用戶選擇多個項。

請參閱有關創建上下文菜單的部分。

彈出菜單

彈出菜單顯示垂直列表中的項目列表,該列表錨定到調用菜單的視圖。提供與特定內容相關的動作溢出或爲命令的第二部分提供選項是有益的。彈出菜單中的操作不應直接影響相應的內容 - 這是上下文操作的用途。而是,彈出菜單用於與活動中的內容區域相關的擴展操作。

請參閱有關創建彈出菜單的部分。

在XML中定義菜單


對於所有菜單類型,Android提供標準XML格式來定義菜單項。您應該在XML菜單資源中定義菜單及其所有項目,而不是在活動代碼中構建菜單。然後,您可以在活動或片段中誇大菜單資源(將其作爲Menu對象加載)。

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

  • 在XML中可視化菜單結構更容易。
  • 它將菜單內容與應用程序的行爲代碼分開。
  • 它允許您通過利用應用程序資源框架爲不同的平臺版本,屏幕大小和其他配置創建備用菜單配置。

要定義菜單,請在項目的res / menu /目錄中創建XML文件,並使用以下元素構建菜單:

<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"
          android:showAsAction="ifRoom"/>
    <item android:id="@+id/help"
          android:icon="@drawable/ic_help"
          android:title="@string/help" />
</menu>

<item>元素支持幾個可用於定義項目外觀和行爲的屬性。上面菜單中的項目包括以下屬性:

android:id

項目唯一的資源ID,允許應用程序在用戶選擇項目時識別該項目。

android:icon

對drawable的引用,用作項目的圖標。

android:title

對用作項目標題的字符串的引用。

android:showAsAction

指定此項目應在應用欄中顯示爲操作項的時間和方式。

這些是您應該使用的最重要的屬性,但還有更多可用的屬性。有關所有受支持屬性的信息,請參閱“菜單資源”文檔。

您可以通過添加<menu>元素作爲<item>的子項,在任何菜單(子菜單除外)中爲項目添加子菜單。當您的應用程序具有許多可以組織到主題中的功能(如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>

要使用活動中的菜單,需要使用MenuInflater.inflate()來擴展菜單資源(將XML資源轉換爲可編程對象)。在以下部分中,您將看到如何爲每種菜單類型爲菜單充氣。

創建選項菜單


圖1.瀏覽器中的選項菜單,在Android 2.3上。

選項菜單中應包含與當前活動上下文相關的操作和其他選項,例如“搜索”,“撰寫電子郵件”和“設置”。

選項菜單中的項目出現在屏幕上的位置取決於您爲其開發應用程序的版本:

  • 如果您已經開發了Android 2.3.x(API級別10)或更低版本的應用程序,當用戶按下Menu按鈕時,選項菜單的內容將顯示在屏幕底部,如圖1所示。打開時,第一個可見部分是圖標菜單,最多可容納六個菜單項。如果您的菜單包含六個以上的項目,Android會將第六個項目和其餘項目放入溢出菜單,用戶可以通過選擇更多來打開該菜單。
  • 如果您已經開發了適用於Android 3.0(API級別11)及更高版本的應用程序,則可以在應用欄中找到選項菜單中的項目。默認情況下,系統會將所有項目置於操作溢出中,用戶可以使用應用欄右側的操作溢出圖標(或按設備菜單按鈕,如果可用)顯示該項目。要啓用對重要操作的快速訪問,可以通過將android:showAsAction =“ifRoom”添加到相應的<item>元素來促使應用欄中顯示一些項目(參見圖2)。

有關操作項和其他應用欄行爲的更多信息,請參閱添加App Bar培訓課程。

圖2. Honeycomb Gallery應用程序中的App欄,顯示導航選項卡和攝像機操作項(以及操作溢出按鈕)。

您可以從Activity子類或Fragment子類聲明選項菜單的項。如果您的活動和片段都爲選項菜單聲明瞭項目,則它們將在UI中合併。首先顯示活動的項目,然後按照每個片段添加到活動的順序顯示每個片段的項目。如有必要,您可以在需要移動的每個<item>中使用android:orderInCategory屬性重新排序菜單項。

要指定活動的選項菜單,請覆蓋onCreateOptionsMenu()(片段提供自己的onCreateOptionsMenu()回調)。在此方法中,您可以將菜單資源(在XML中定義)擴展到回調中提供的菜單中。例如:

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

您還可以使用add()添加菜單項,並使用findItem()檢索項目,以使用MenuItem API修改其屬性。

如果您已經開發了適用於Android 2.3.x及更低版本的應用程序,系統會在用戶首次打開菜單時調用onCreateOptionsMenu()來創建選項菜單。如果您是針對Android 3.0及更高版本開發的,系統會在啓動活動時調用onCreateOptionsMenu(),以便嚮應用欄顯示項目。

處理點擊事件

當用戶從選項菜單中選擇一個項目(包括應用欄中的操作項)時,系統將調用您的活動的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)。

如果您的活動包含片段,則系統首先爲活動調用onOptionsItemSelected(),然後爲每個片段調用(按照添加每個片段的順序),直到一個返回true或已調用所有片段。

提示:Android 3.0增加了使用android:onClick屬性爲XML中的菜單項定義點擊行爲的功能。屬性的值必須是使用菜單的活動定義的方法的名稱。該方法必須是公共的並接受單個MenuItem參數 - 當系統調用此方法時,它會傳遞所選的菜單項。有關更多信息和示例,請參閱菜單資源文檔。

提示:如果您的應用程序包含多個活動,並且其中一些活動提供相同的選項菜單,請考慮創建除onCreateOptionsMenu()和onOptionsItemSelected()方法之外不執行任何操作的活動。然後爲應該共享相同選項菜單的每個活動擴展此類。這樣,您可以管理一組代碼來處理菜單操作,每個後代類都繼承菜單行爲。如果要將菜單項添加到其中一個後代活動,請覆蓋該活動中的onCreateOptionsMenu()。調用super.onCreateOptionsMenu(菜單)以創建原始菜單項,然後使用menu.add()添加新菜單項。您還可以覆蓋單個菜單項的超類的行爲。

在運行時更改菜單項

在系統調用onCreateOptionsMenu()之後,它會保留您填充的菜單的實例,並且不會再次調用onCreateOptionsMenu(),除非由於某種原因菜單失效。但是,您應該僅使用onCreateOptionsMenu()來創建初始菜單狀態,而不是在活動生命週期中進行更改。

如果要根據活動生命週期中發生的事件修改選項菜單,可以在onPrepareOptionsMenu()方法中執行此操作。此方法會將Menu對象傳遞給當前存在,以便您可以對其進行修改,例如添加,刪除或禁用項目。 (片段還提供onPrepareOptionsMenu()回調。)

在Android 2.3.x及更低版本中,每次用戶打開選項菜單(按菜單按鈕)時,系統都會調用onPrepareOptionsMenu()。

在Android 3.0及更高版本中,當應用欄中顯示菜單項時,選項菜單被視爲始終打開。當事件發生並且您想要執行菜單更新時,必須調用invalidateOptionsMenu()以請求系統調用onPrepareOptionsMenu()。

注意:您永遠不應該根據當前焦點視圖更改選項菜單中的項目。在觸摸模式下(當用戶沒有使用軌跡球或d-pad時),視圖無法獲得焦點,因此您不應該使用焦點作爲修改選項菜單中項目的基礎。如果要提供對視圖具有上下文相關性的菜單項,請使用上下文菜單。

創建上下文菜單


圖3.浮動上下文菜單(左)和上下文操作欄(右)的屏幕截圖。

上下文菜單提供影響UI中特定項目或上下文框架的操作。您可以爲任何視圖提供上下文菜單,但它們通常用於ListView,GridView或其他視圖集合中的項目,用戶可以在其中對每個項目執行直接操作。

有兩種方法可以提供上下文操作:

  • 在浮動上下文菜單中。當用戶在聲明支持上下文菜單的視圖上執行長按(按住)時,菜單顯示爲菜單項的浮動列表(類似於對話框)。用戶可以一次對一個項目執行上下文操作。
  • 在上下文動作模式中。此模式是ActionMode的系統實現,它在屏幕頂部顯示一個上下文操作欄,其中包含影響所選項目的操作項。當此模式處於活動狀態時,用戶可以同時對多個項目執行操作(如果您的應用允許)。

注意:上下文操作模式在Android 3.0(API級別11)及更高版本上可用,並且是可用時顯示上下文操作的首選技術。如果您的應用支持低於3.0的版本,那麼您應該回到這些設備上的浮動上下文菜單。

創建浮動上下文菜單

要提供浮動上下文菜單:

1.通過調用registerForContextMenu()註冊上下文菜單應關聯的視圖,並將其傳遞給View。

如果您的活動使用ListView或GridView並且您希望每個項目都提供相同的上下文菜單,請通過將ListView或GridView傳遞給registerForContextMenu()來註冊上下文菜單的所有項目。

2.在Activity或Fragment中實現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對象,後者提供有關所選項的其他信息。如果您的活動有多個視圖,每個視圖都提供不同的上下文菜單,您可以使用這些參數來確定要擴展的上下文菜單。

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。如果不處理菜單項,則應將菜單項傳遞給超類實現。如果您的活動包含片段,則活動首先接收此回調。通過在未處理時調用超類,系統將事件傳遞給每個片段中的相應回調方法,一次一個(按照每個片段的順序添加),直到返回true或false。 (Activity和android.app.Fragment的默認實現返回false,因此在未處理時應始終調用超類。)

使用上下文操作模式

上下文操作模式是ActionMode的系統實現,其將用戶交互集中於執行上下文操作。當用戶通過選擇項目啓用此模式時,屏幕頂部會出現一個上下文操作欄,以顯示用戶可以對當前所選項目執行的操作。啓用此模式後,用戶可以選擇多個項目(如果允許),取消選擇項目,然後繼續在活動中導航(儘可能多地允許)。當用戶取消選擇所有項目,按BACK按鈕或選擇欄左側的完成操作時,操作模式被禁用,上下文操作欄消失。

注意:上下文操作欄不一定與應用欄相關聯。它們獨立運行,即使上下文操作欄在視覺上超過應用欄位置。

對於提供上下文操作的視圖,通常應該在兩個事件(或兩者)之一上調用上下文操作模式:

  • 用戶在視圖上執行長按。
  • 用戶在視圖中選擇複選框或類似的UI組件。

應用程序如何調用上下文操作模式並定義每個操作的行爲取決於您的設計。基本上有兩種設計:

  • 對於單個任意視圖的上下文操作。
  • 對於ListView或GridView中的項目組的批處理上下文操作(允許用戶選擇多個項目並對它們執行所有操作)。

以下部分描述了每個方案所需的設置。

爲各個視圖啓用上下文操作模式

如果只想在用戶選擇特定視圖時調用上下文操作模式,則應該:

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。在下一步中,您將看到它是如何初始化的,以及如何在活動或片段中保存成員變量是有用的。

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中啓用批處理上下文操作

如果ListView或GridView(或AbsListView的另一個擴展)中有一組項目,並且希望允許用戶執行批處理操作,則應該:

  • 實現AbsListView.MultiChoiceModeListener接口,並使用setMultiChoiceModeListener()爲視圖組設置它。在偵聽器的回調方法中,您可以指定上下文操作欄的操作,響應操作項上的單擊事件,以及處理從ActionMode.Callback接口繼承的其他回調。
  • 使用CHOICE_MODE_MULTIPLE_MODAL參數調用setChoiceMode()。

例如:

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的模式菜單。如果有空間,它將顯示在錨點視圖下方,否則顯示在視圖上方。它對以下內容很有用:

  • 爲與特定內容相關的操作提供溢出式菜單(例如Gmail的電子郵件標題,如圖4所示)。

     

注意:這與上下文菜單不同,上下文菜單通常用於影響所選內容的操作。對於影響所選內容的操作,請使用上下文操作模式或浮動上下文菜單。

  • 提供命令語句的第二部分(例如標記爲“添加”的按鈕,該按鈕產生具有不同“添加”選項的彈出菜單)。
  • 提供類似於Spinner的下拉列表,不會保留持久選擇。

注意:PopupMenu可用於API級別11及更高級別。

如果您使用XML定義菜單,則可以在此處顯示彈出菜單:

1.使用其構造函數實例化PopupMenu,該構造函數接受當前應用程序Context和菜單應錨定到的View。

2.使用MenuInflater將菜單資源擴展爲PopupMenu.getMenu()返回的Menu對象。

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" />

然後,該活動可以顯示如下彈出菜單:

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

在API級別14及更高級別中,您可以將彈出菜單的兩行與PopupMenu.inflate()組合在一起。

當用戶選擇項目或觸摸菜單區域外時,菜單被解除。您可以使用PopupMenu.OnDismissListener偵聽dismiss事件。

處理點擊事件

要在用戶選擇菜單項時執行操作,您必須實現PopupMenu.OnMenuItemClickListener接口,並通過調用setOnMenuItemclickListener()將其註冊到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;
    }
}

創建菜單組


菜單組是共享某些特徵的菜單項的集合。通過羣組,您可以:

  • 使用setGroupVisible()顯示或隱藏所有項目
  • 使用setGroupEnabled()啓用或禁用所有項目
  • 指定是否可以使用setGroupCheckable()檢查所有項目

您可以通過在菜單資源中的<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顯示了一個子菜單,其中的項目可通過單選按鈕進行檢查。

注意:圖標菜單中的菜單項(從選項菜單中)無法顯示覆選框或單選按鈕。如果您選擇在圖標菜單中選中項目,則必須通過在每次狀態更改時交換圖標和/或文本來手動指示選中狀態。

您可以使用<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()設置檢查狀態。例如:

@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啓動活動(無論它是您的應用程序中的活動還是其他應用程序)。當您知道要使用的意圖並具有應該啓動意圖的特定菜單項時,您可以在適當的on-item-selected的回調方法(例如onOptionsItemSelected()回調)期間使用startActivity()執行intent。

但是,如果您不確定用戶的設備是否包含處理意圖的應用程序,則添加調用它的菜單項可能會導致菜單項無效,因爲意圖可能無法解析爲活動。要解決此問題,當Android在設備上查找處理您意圖的活動時,Android會讓您動態地將菜單項添加到菜單中。

要根據接受意圖的可用活動添加菜單項:

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

對於找到的每個提供與定義的意圖匹配的意圖過濾器的活動,添加一個菜單項,使用意圖過濾器的android:標籤中的值作爲菜單項標題,將應用程序圖標作爲菜單項圖標。 addIntentOptions()方法返回添加的菜單項數。

注意:調用addIntentOptions()時,它會覆蓋第一個參數中指定的菜單組的所有菜單項。

允許您的活動添加到其他菜單

您還可以將活動服務提供給其他應用程序,因此您的應用程序可以包含在其他應用程序的菜單中(反轉上述角色)。

要包含在其他應用程序菜單中,您需要像往常一樣定義intent過濾器,但請確保包含intent過濾器類別的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>

閱讀有關在Intents和Intent Filters文檔中編寫intent過濾器的更多信息。

有關使用此技術的示例應用程序,請參閱Note Pad示例代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章