安卓 topic-菜單 Menu

http://developer.android.youdaxue.com/guide/topics/ui/menus.html

菜單是許多應(yīng)用類型中常見的用戶界面組件撒会。要提供熟悉而一致的用戶體驗(yàn)挠锥,您應(yīng)使用 Menu API 呈現(xiàn) Activity 中的用戶操作和其他選項(xiàng)驰坊。
從 Android 3.0(API 級(jí)別 11)開始姿锭,采用 Android 技術(shù)的設(shè)備不必再提供一個(gè)專用“菜單”按鈕。隨著這種改變扒披,Android 應(yīng)用需擺脫對(duì)包含 6 個(gè)項(xiàng)目的傳統(tǒng)菜單面板的依賴沸停,取而代之的是要提供一個(gè)應(yīng)用欄來呈現(xiàn)常見的用戶操作良狈。
盡管某些菜單項(xiàng)的設(shè)計(jì)和用戶體驗(yàn)已發(fā)生改變,但定義一系列操作和選項(xiàng)所使用的語義仍是以 Menu API 為基礎(chǔ)黍特。本指南將介紹所有 Android 版本系統(tǒng)中三種基本菜單或操作呈現(xiàn)效果的創(chuàng)建方法:

  • 選項(xiàng)菜單和應(yīng)用欄
    選項(xiàng)菜單是某個(gè) Activity 的主菜單項(xiàng)蛙讥, 供您放置對(duì)應(yīng)用產(chǎn)生全局影響的操作,如“搜索”灭衷、“撰寫電子郵件”和“設(shè)置”次慢。請(qǐng)參閱創(chuàng)建選項(xiàng)菜單部分。

  • 上下文菜單和上下文操作模式
    上下文菜單是用戶長按某一元素時(shí)出現(xiàn)的浮動(dòng)菜單翔曲。 它提供的操作將影響所選內(nèi)容或上下文框架迫像。上下文操作模式在屏幕頂部欄顯示影響所選內(nèi)容的操作項(xiàng)目,并允許用戶選擇多項(xiàng)瞳遍。
    請(qǐng)參閱創(chuàng)建上下文菜單部分闻妓。

  • 彈出菜單
    彈出菜單將以垂直列表形式顯示一系列項(xiàng)目,這些項(xiàng)目將錨定到調(diào)用該菜單的視圖中掠械。 它特別適用于提供與特定內(nèi)容相關(guān)的大量操作由缆,或者為命令的另一部分提供選項(xiàng)注祖。 彈出菜單中的操作不會(huì)直接影響對(duì)應(yīng)的內(nèi)容,而上下文操作則會(huì)影響均唉。 相反是晨,彈出菜單適用于與您 Activity 中的內(nèi)容區(qū)域相關(guān)的擴(kuò)展操作。請(qǐng)參閱創(chuàng)建彈出菜單部分舔箭。

使用 XML 定義菜單

對(duì)于所有菜單類型罩缴,Android 提供了標(biāo)準(zhǔn)的 XML 格式來定義菜單項(xiàng)。您應(yīng)在 XML 菜單資源中定義菜單及其所有項(xiàng)限嫌,而不是在 Activity 的代碼中構(gòu)建菜單靴庆。定義后,您可以在 Activity 或片段中擴(kuò)充菜單資源(將其作為 Menu
對(duì)象加載)怒医。

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

  • 更易于使用 XML 可視化菜單結(jié)構(gòu)
  • 將菜單內(nèi)容與應(yīng)用的行為代碼分離
  • 允許您利用應(yīng)用資源框架,為不同的平臺(tái)版本稚叹、屏幕尺寸和其他配置創(chuàng)建備用菜單配置

以下是名為 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>

要在 Activity 中使用菜單焰薄,您需要使用 [MenuInflater.inflate()](http://developer.android.youdaxue.com/reference/android/view/MenuInflater.html#inflate(int, android.view.Menu)) 擴(kuò)充菜單資源(將 XML 資源轉(zhuǎn)換為可編程對(duì)象)。在下文中扒袖,您將了解如何擴(kuò)充每種類型的菜單塞茅。

創(chuàng)建選項(xiàng)菜單

在選項(xiàng)菜單中,您應(yīng)當(dāng)包括與當(dāng)前 Activity 上下文相關(guān)的操作和其他選項(xiàng)季率,如“搜索”野瘦、“撰寫電子郵件”和“設(shè)置”。
選項(xiàng)菜單中的項(xiàng)目在屏幕上的顯示位置取決于您開發(fā)的應(yīng)用所適用的 Android 版本:

  • 如果您開發(fā)的應(yīng)用適用于 Android 2.3.x(API 級(jí)別 10)或更低版本飒泻,則當(dāng)用戶按“菜單”按鈕時(shí)鞭光,選項(xiàng)菜單的內(nèi)容會(huì)出現(xiàn)在屏幕底部,如圖 1 所示泞遗。打開時(shí)惰许,第一個(gè)可見部分是圖標(biāo)菜單,其中包含多達(dá) 6 個(gè)菜單項(xiàng)史辙。 如果菜單包括 6 個(gè)以上項(xiàng)目汹买,則 Android 會(huì)將第六項(xiàng)和其余項(xiàng)目放入溢出菜單。用戶可以通過選擇“更多”打開該菜單聊倔。
  • 如果您開發(fā)的應(yīng)用適用于 Android 3.0(API 級(jí)別 11)及更高版本晦毙,則選項(xiàng)菜單中的項(xiàng)目將出現(xiàn)在應(yīng)用欄中。 默認(rèn)情況下耙蔑,系統(tǒng)會(huì)將所有項(xiàng)目均放入操作溢出菜單中结序。用戶可以使用應(yīng)用欄右側(cè)的操作溢出菜單圖標(biāo)(或者,通過按設(shè)備“菜單”按鈕(如有))顯示操作溢出菜單纵潦。 要支持快速訪問重要操作徐鹤,您可以將android:showAsAction="ifRoom"
    添加到對(duì)應(yīng)的 <item>元素垃环,從而將幾個(gè)項(xiàng)目提升到應(yīng)用欄中(請(qǐng)參閱圖 2)。如需了解有關(guān)操作項(xiàng)目和其他應(yīng)用欄行為的詳細(xì)信息返敬,請(qǐng)參閱添加應(yīng)用欄培訓(xùn)課程遂庄。

您可以通過 Activity 子類或 Fragment 子類為選項(xiàng)菜單聲明項(xiàng)目。如果您的 Activity 和片段均為選項(xiàng)菜單聲明項(xiàng)目劲赠,則這些項(xiàng)目將合并到 UI 中涛目。 系統(tǒng)將首先顯示 Activity 的項(xiàng)目,隨后按每個(gè)片段添加到 Activity 中的順序顯示各片段的項(xiàng)目凛澎。 如有必要霹肝,您可以使用 android:orderInCategory 屬性,對(duì)需要移動(dòng)的每個(gè) <item> 中的菜單項(xiàng)重新排序塑煎。

要為 Activity 指定選項(xiàng)菜單沫换,請(qǐng)重寫 onCreateOptionsMenu()(片段會(huì)提供自己的 onCreateOptionsMenu() 回調(diào))。通過此方法最铁,您可以將菜單資源(使用 XML 定義)擴(kuò)充到回調(diào)中提供的 Menu 中讯赏。 例如:

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

如果菜單按鈕與Fragment關(guān)聯(lián),則確保在Fragment的 onCreate 方法中調(diào)用 setHasOptionsMenu(true)冷尉。

此外漱挎,您還可以使用 add() 添加菜單項(xiàng),并使用 findItem() 檢索項(xiàng)目雀哨,以便使用 MenuItem API 修改其屬性磕谅。
如果您開發(fā)的應(yīng)用適用于 Android 2.3.x 及更低版本,則當(dāng)用戶首次打開選項(xiàng)菜單時(shí)雾棺,系統(tǒng)會(huì)調(diào)用 onCreateOptionsMenu() 來創(chuàng)建該菜單膊夹。 如果您開發(fā)的應(yīng)用適用于 Android 3.0 及更高版本,則系統(tǒng)將在啟動(dòng) Activity 時(shí)調(diào)用 onCreateOptionsMenu()垢村,以便向應(yīng)用欄顯示項(xiàng)目割疾。

處理點(diǎn)擊事件

用戶從選項(xiàng)菜單中選擇項(xiàng)目(包括應(yīng)用欄中的操作項(xiàng)目)時(shí)嚎卫,系統(tǒng)將調(diào)用 Activity 的 onOptionsItemSelected() 方法嘉栓。 此方法將傳遞所選的 MenuItem。您可以通過調(diào)用 getItemId() 方法來識(shí)別項(xiàng)目拓诸,該方法將返回菜單項(xiàng)的唯一 ID(由菜單資源中的 android:id 屬性定義侵佃,或通過提供給 add() 方法的整型數(shù)定義)。 您可以將此 ID 與已知的菜單項(xiàng)匹配奠支,以執(zhí)行適當(dāng)?shù)牟僮鞑霰病@纾?/p>

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

成功處理菜單項(xiàng)后,系統(tǒng)將返回 true倍谜。如果未處理菜單項(xiàng)迈螟,則應(yīng)調(diào)用 onOptionsItemSelected() 的超類實(shí)現(xiàn)(默認(rèn)實(shí)現(xiàn)將返回 false)叉抡。
如果 Activity 包括片段,則系統(tǒng)將依次為 Activity 和每個(gè)片段(按照每個(gè)片段的添加順序)調(diào)用 onOptionsItemSelected()答毫,直到有一個(gè)返回結(jié)果為 true 或所有片段均調(diào)用完畢為止褥民。

在運(yùn)行時(shí)更改菜單項(xiàng)

系統(tǒng)調(diào)用 onCreateOptionsMenu() 后,將保留您填充的 Menu 實(shí)例洗搂。除非菜單由于某些原因而失效消返,否則不會(huì)再次調(diào)用 onCreateOptionsMenu()。但是耘拇,
您僅應(yīng)使用 onCreateOptionsMenu() 來創(chuàng)建初始菜單狀態(tài)撵颊,而不應(yīng)使用它在 Activity 生命周期中執(zhí)行任何更改。

如需根據(jù)在 Activity 生命周期中發(fā)生的事件修改選項(xiàng)菜單惫叛,則可通過 onPrepareOptionsMenu() 方法執(zhí)行此操作倡勇。此方法向您傳遞 Menu 對(duì)象(因?yàn)樵搶?duì)象目前存在),以便您能夠?qū)ζ溥M(jìn)行修改挣棕,如添加译隘、移除或禁用項(xiàng)目。(此外洛心,片段還提供 onPrepareOptionsMenu() 回調(diào)固耘。)

在 Android 2.3.x 及更低版本中,每當(dāng)用戶打開選項(xiàng)菜單時(shí)(按“菜單”按鈕)词身,系統(tǒng)均會(huì)調(diào)用 onPrepareOptionsMenu()厅目。

在 Android 3.0 及更高版本中,當(dāng)菜單項(xiàng)顯示在應(yīng)用欄中時(shí)法严,選項(xiàng)菜單被視為始終處于打開狀態(tài)损敷。 發(fā)生事件時(shí),如果您要執(zhí)行菜單更新深啤,則必須調(diào)用 invalidateOptionsMenu() 來請(qǐng)求系統(tǒng)調(diào)用 onPrepareOptionsMenu()拗馒。

創(chuàng)建上下文菜單

上下文菜單提供了許多操作,這些操作影響 UI 中的特定項(xiàng)目或上下文框架溯街。您可以為任何視圖提供上下文菜單诱桂,但這些菜單通常用于 ListView、GridView 或用戶可直接操作每個(gè)項(xiàng)目的其他視圖集合中的項(xiàng)目呈昔。

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

  • 使用浮動(dòng)上下文菜單挥等。用戶長按(按住)一個(gè)聲明支持上下文菜單的視圖時(shí)堤尾,菜單顯示為菜單項(xiàng)的浮動(dòng)列表(類似于對(duì)話框)肝劲。 用戶一次可對(duì)一個(gè)項(xiàng)目執(zhí)行上下文操作。
  • 使用上下文操作模式。此模式是 ActionMode 的系統(tǒng)實(shí)現(xiàn)辞槐,它將在屏幕頂部顯示上下文操作欄掷漱,其中包括影響所選項(xiàng)的操作項(xiàng)目。當(dāng)此模式處于活動(dòng)狀態(tài)時(shí)榄檬,用戶可以同時(shí)對(duì)多項(xiàng)執(zhí)行操作(如果應(yīng)用允許)切威。

注:上下文操作模式可用于 Android 3.0(API 級(jí)別 11)及更高版本,是顯示上下文操作(如果可用)的首選方法丙号。如果應(yīng)用支持低于 3.0 版本的系統(tǒng)先朦,則應(yīng)在這些設(shè)備上回退到浮動(dòng)上下文菜單。

浮動(dòng)上下文菜單(左)和上下文操作欄(右)的屏幕截圖犬缨。
創(chuàng)建浮動(dòng)上下文菜單

要提供浮動(dòng)上下文菜單喳魏,請(qǐng)執(zhí)行以下操作:

  1. 通過調(diào)用 registerForContextMenu(),注冊(cè)應(yīng)與上下文菜單關(guān)聯(lián)的 View
    并將其傳遞給 View怀薛。如果 Activity 使用 ListView
    GridView 且您希望每個(gè)項(xiàng)目均提供相同的上下文菜單刺彩,請(qǐng)通過將 ListView
    GridView傳遞給registerForContextMenu(),為上下文菜單注冊(cè)所有項(xiàng)目枝恋。
  2. ActivityFragment 中實(shí)現(xiàn) [onCreateContextMenu()](http://developer.android.youdaxue.com/reference/android/view/View.OnCreateContextMenuListener.html#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)) 方法创倔。當(dāng)注冊(cè)后的視圖收到長按事件時(shí),系統(tǒng)將調(diào)用您的 [onCreateContextMenu()](http://developer.android.youdaxue.com/reference/android/view/View.OnCreateContextMenuListener.html#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)) 方法焚碌。在此方法中畦攘,您通常可通過擴(kuò)充菜單資源來定義菜單項(xiàng)十电。例如:
@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 允許您通過菜單資源擴(kuò)充上下文菜單知押。回調(diào)方法參數(shù)包括用戶所選的 View鹃骂,以及一個(gè)提供有關(guān)所選項(xiàng)的附加信息的ContextMenu.ContextMenuInfo 對(duì)象台盯。如果 Activity 有多個(gè)視圖,每個(gè)視圖均提供不同的上下文菜單畏线,則可使用這些參數(shù)確定要擴(kuò)充的上下文菜單静盅。

  1. 實(shí)現(xiàn) onContextItemSelected()。用戶選擇菜單項(xiàng)時(shí)寝殴,系統(tǒng)將調(diào)用此方法蒿叠,以便您能夠執(zhí)行適當(dāng)?shù)牟僮鳌?例如:
@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() 方法將查詢所選菜單項(xiàng)的 ID,您應(yīng)使用 android:id 屬性將此 ID 分配給 XML 中的每個(gè)菜單項(xiàng)杯矩,如使用 XML 定義菜單部分所示栈虚。成功處理菜單項(xiàng)后袖外,系統(tǒng)將返回 true史隆。如果未處理菜單項(xiàng),則應(yīng)將菜單項(xiàng)傳遞給超類實(shí)現(xiàn)曼验。 如果 Activity 包括片段泌射,則 Activity 將先收到此回調(diào)粘姜。 通過在未處理的情況下調(diào)用超類,系統(tǒng)會(huì)將事件逐一傳遞給每個(gè)片段中相應(yīng)的回調(diào)方法(按照每個(gè)片段的添加順序)熔酷,直到返回 true 或 false 為止孤紧。(Activity 和 android.app.Fragment 的默認(rèn)實(shí)現(xiàn)返回 false,因此您始終應(yīng)在未處理的情況下調(diào)用超類拒秘。)

使用上下文操作模式

上下文操作模式是 ActionMode 的一種系統(tǒng)實(shí)現(xiàn)号显,它將用戶交互的重點(diǎn)轉(zhuǎn)到執(zhí)行上下文操作上。用戶通過選擇項(xiàng)目啟用此模式時(shí)躺酒,屏幕頂部將出現(xiàn)一個(gè)“上下文操作欄”押蚤,顯示用戶可對(duì)當(dāng)前所選項(xiàng)執(zhí)行的操作。 啟用此模式后羹应,用戶可以選擇多個(gè)項(xiàng)目(若您允許)揽碘、取消選擇項(xiàng)目以及繼續(xù)在 Activity 內(nèi)導(dǎo)航(在您允許的最大范圍內(nèi))。 當(dāng)用戶取消選擇所有項(xiàng)目园匹、按“返回”按鈕或選擇操作欄左側(cè)的“完成”操作時(shí)雳刺,該操作模式將會(huì)停用,且上下文操作欄將會(huì)消失裸违。

注:上下文操作欄不一定與應(yīng)用欄相關(guān)聯(lián)掖桦。 盡管表面上看來上下文操作欄取代了應(yīng)用欄的位置,但事實(shí)上二者獨(dú)立運(yùn)行供汛。

對(duì)于提供上下文操作的視圖滞详,當(dāng)出現(xiàn)以下兩個(gè)事件(或之一)時(shí),您通常應(yīng)調(diào)用上下文操作模式:

  • 用戶長按視圖紊馏。
  • 用戶選中復(fù)選框或視圖內(nèi)的類似 UI 組件料饥。

應(yīng)用如何調(diào)用上下文操作模式以及如何定義每個(gè)操作的行為,具體取決于您的設(shè)計(jì)朱监。 設(shè)計(jì)基本上分為兩種:

  • 針對(duì)單個(gè)任意視圖的上下文操作岸啡。
  • 針對(duì) ListViewGridView中項(xiàng)目組的批處理上下文操作(允許用戶選擇多個(gè)項(xiàng)目并針對(duì)所有項(xiàng)目執(zhí)行操作)。

下文介紹每種場(chǎng)景所需的設(shè)置赫编。

為單個(gè)視圖啟用上下文操作模式

如果希望僅當(dāng)用戶選擇特定視圖時(shí)才調(diào)用上下文操作模式巡蘸,則應(yīng):

  1. 實(shí)現(xiàn) ActionMode.Callback 接口。在其回調(diào)方法中擂送,您既可以為上下文操作欄指定操作悦荒,又可以響應(yīng)操作項(xiàng)目的點(diǎn)擊事件,還可以處理操作模式的其他生命周期事件嘹吨。
  2. 當(dāng)需要顯示操作欄時(shí)(例如搬味,用戶長按視圖),請(qǐng)調(diào)用 startActionMode()
  1. 例如:實(shí)現(xiàn) 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;
    }
};

請(qǐng)注意碰纬,這些事件回調(diào)與選項(xiàng)菜單的回調(diào)幾乎完全相同萍聊,只是其中每個(gè)回調(diào)還會(huì)傳遞與事件相關(guān)聯(lián)的 ActionMode 對(duì)象。您可以使用 ActionMode API 對(duì) CAB 進(jìn)行各種更改悦析,例如:使用 setTitle()setSubtitle()(這對(duì)指示要選擇多少個(gè)項(xiàng)目非常有用)修改標(biāo)題和副標(biāo)題寿桨。另請(qǐng)注意,操作模式被銷毀時(shí)强戴,上述示例會(huì)將 mActionMode 變量設(shè)置為 null亭螟。 在下一步中,您將了解如何初始化該變量骑歹,以及保存 Activity 或片段中的成員變量有何作用媒佣。

  1. 調(diào)用 startActionMode() 以便適時(shí)啟用上下文操作模式,例如:響應(yīng)對(duì) 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;
    }
});

當(dāng)您調(diào)用 startActionMode() 時(shí)陵刹,系統(tǒng)將返回已創(chuàng)建的 ActionMode默伍。通過將其保存在成員變量中,您可以更改上下文操作欄來響應(yīng)其他事件衰琐。 在上述示例中也糊, ActionMode 用于在啟動(dòng)操作模式之前檢查成員是否為空,以確保當(dāng) ActionMode 實(shí)例已激活時(shí)不再重建該實(shí)例羡宙。

在 ListView 或 GridView 中啟用批處理上下文操作

如果您在 ListView
GridView 中有一組項(xiàng)目(或 AbsListView 的其他擴(kuò)展)狸剃,且需要允許用戶執(zhí)行批處理操作,則應(yīng):

例如:

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

就這么簡(jiǎn)單⊙荡耄現(xiàn)在,當(dāng)用戶通過長按選擇項(xiàng)目時(shí)光羞,系統(tǒng)即會(huì)調(diào)用 [onCreateActionMode()](http://developer.android.youdaxue.com/reference/android/view/ActionMode.Callback.html#onCreateActionMode(android.view.ActionMode, android.view.Menu)) 方法绩鸣,并顯示包含指定操作的上下文操作欄。當(dāng)上下文操作欄可見時(shí)纱兑,用戶可以選擇其他項(xiàng)目呀闻。
在某些情況下,如果上下文操作提供常用的操作項(xiàng)目潜慎,則您可能需要添加一個(gè)復(fù)選框或類似的 UI 元素來支持用戶選擇項(xiàng)目捡多,這是因?yàn)樗麄兛赡軟]有發(fā)現(xiàn)長按行為蓖康。用戶選中該復(fù)選框時(shí),您可以通過使用 [setItemChecked()](http://developer.android.youdaxue.com/reference/android/widget/AbsListView.html#setItemChecked(int, boolean)) 將相應(yīng)的列表項(xiàng)設(shè)置為選中狀態(tài)局服,以此調(diào)用上下文操作模式。

創(chuàng)建彈出菜單

PopupMenu 是錨定到 View 的模態(tài)菜單驳遵。如果空間足夠淫奔,它將顯示在定位視圖下方,否則顯示在其上方堤结。它適用于:

  • 為與特定內(nèi)容確切相關(guān)的操作提供溢出樣式菜單(例如唆迁,Gmail 的電子郵件標(biāo)頭,如圖所示)竞穷。
Gmail 應(yīng)用中的彈出菜單唐责,錨定到右上角的溢出按鈕。

注:這與上下文菜單不同瘾带,后者通常用于影響所選內(nèi)容的操作。 **對(duì)于影響所選內(nèi)容的操作看政,請(qǐng)使用上下文操作模式浮動(dòng)上下文菜單

  • 提供命令語句的另一部分(例如允蚣,標(biāo)記為“添加”且使用不同的“添加”選項(xiàng)生成彈出菜單的按鈕)。
  • 提供類似于 Spinner 且不保留永久選擇的下拉菜單森渐。

注:PopupMenu 在 API 級(jí)別 11 及更高版本中可用。

如果使用 XML 定義菜單同衣,則顯示彈出菜單的方法如下:

  1. 實(shí)例化 PopupMenu 及其構(gòu)造函數(shù),該函數(shù)將提取當(dāng)前應(yīng)用的 Context 以及菜單應(yīng)錨定到的 View壶运。
  2. 使用 MenuInflater 將菜單資源擴(kuò)充到 PopupMenu.getMenu() 返回的 Menu 對(duì)象中乳怎。
  3. 調(diào)用 PopupMenu.show()

例如前弯,以下是一個(gè)使用 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();
}

在 API 級(jí)別 14 及更高版本中,您可以將兩行合并在一起恕出,使用 PopupMenu.inflate() 擴(kuò)充菜單询枚。當(dāng)用戶選擇項(xiàng)目或觸摸菜單以外的區(qū)域時(shí),系統(tǒng)即會(huì)清除此菜單浙巫。 您可使用 PopupMenu.OnDismissListener 偵聽清除事件金蜀。

處理點(diǎn)擊事件

要在用戶選擇菜單項(xiàng)時(shí)執(zhí)行操作刷后,您必須實(shí)現(xiàn) PopupMenu.OnMenuItemClickListener 接口,并通過調(diào)用 setOnMenuItemclickListener() 將其注冊(cè)到PopupMenu渊抄。 用戶選擇項(xiàng)目時(shí)尝胆,系統(tǒng)會(huì)在接口中調(diào)用 onMenuItemClick() 回調(diào)。
例如:

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;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末护桦,一起剝皮案震驚了整個(gè)濱河市含衔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌二庵,老刑警劉巖贪染,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異催享,居然都是意外死亡杭隙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門因妙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痰憎,“玉大人,你說我怎么就攤上這事攀涵≈” “怎么了据德?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵橱野,是天一觀的道長水援。 經(jīng)常有香客問我茅郎,道長系冗,這世上最難降的妖魔是什么掌敬? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任池磁,我火速辦了婚禮地熄,結(jié)果婚禮上端考,老公的妹妹穿的比我還像新娘跛梗。我一直安慰自己,他們只是感情好顽染,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布粉寞。 她就那樣靜靜地躺著唧垦,像睡著了一般振亮。 火紅的嫁衣襯著肌膚如雪坊秸。 梳的紋絲不亂的頭發(fā)上褒搔,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天星瘾,我揣著相機(jī)與錄音死相,去河邊找鬼算撮。 笑死肮柜,一個(gè)胖子當(dāng)著我的面吹牛审洞,可吹牛的內(nèi)容都是我干的芒澜。 我是一名探鬼主播辣垒,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼部凑,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼涂邀!你這毒婦竟也來了比勉?” 一聲冷哼從身側(cè)響起浩聋,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤赡勘,失蹤者是張志新(化名)和其女友劉穎闸与,沒想到半個(gè)月后践樱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拷邢,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞭稼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年欲虚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了复哆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梯找。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锈锤,死狀恐怖牙咏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摔握,我是刑警寧澤氨淌,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布删咱,位于F島的核電站痰滋,受9級(jí)特大地震影響敲街,放射性物質(zhì)發(fā)生泄漏多艇。R本人自食惡果不足惜像吻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昏名。 院中可真熱鬧轻局,春花似錦仑扑、人聲如沸镇饮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辖源。三九已至希太,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矾湃,已是汗流浹背邀跃。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工坞嘀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丽涩,地道東北人矢渊。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓矮男,卻偏偏與公主長得像毡鉴,于是被迫代替她去往敵國和親猪瞬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容

  • 本節(jié)引言: 本章給大家?guī)淼氖茿ndroid中的Menu(菜單),而在Android中的菜單有如下幾種: Opti...
    侯蛋蛋_閱讀 8,868評(píng)論 0 10
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,304評(píng)論 25 707
  • 1 在Activity中創(chuàng)建菜單 在Activity中重寫兩個(gè)方法 創(chuàng)建資源文件在res目錄下創(chuàng)建menu目錄,用...
    fengcz閱讀 12,096評(píng)論 1 5
  • 3.1. 介紹 現(xiàn)在皱埠,您已經(jīng)安裝了Wireshark并有可能熱衷于開始捕捉您的第一個(gè)數(shù)據(jù)包塞弊。在接下來的章節(jié)中游沿,我們...
    wwyyzz閱讀 1,390評(píng)論 0 1
  • The Hamming distance between two integers is the number o...
    Jarhot閱讀 268評(píng)論 0 0