Android Menu菜單使用

1. 菜單的分類

菜單是Android應(yīng)用中非常重要且常見的組成部分,主要可以分為三類:選項菜單、上下文菜單/上下文操作模式以及彈出菜單。它們的主要區(qū)別如下:

  • 選項菜單
    一個應(yīng)用的主菜單項,用于放置對應(yīng)用產(chǎn)生全局影響的操作,如搜索/設(shè)置。
  • 上下文菜單
    用戶長按某一元素時出現(xiàn)的浮動菜單。它提供的操作將影響所選內(nèi)容,主要應(yīng)用于列表中的每一項元素(如長按列表項彈出刪除對話框)。上下文操作模式將在屏幕頂部欄(菜單欄)顯示影響所選內(nèi)容的操作選項,并允許用戶選擇多項,一般用于對列表類型的數(shù)據(jù)進行批量操作。
  • 彈出菜單
    以垂直列表形式顯示一系列操作選項,一般由某一控件觸發(fā),彈出菜單將顯示在對應(yīng)控件的上方或下方。它適用于提供與特定內(nèi)容相關(guān)的大量操作。

2. 選項菜單

XML定義Menu

使用XML和Java代碼都可以創(chuàng)建Menu。但是在實際開發(fā)中,往往通過XML文件定義Menu,但Menu的部分條目需要動態(tài)顯示,便需要采用java代碼實現(xiàn),使用XML做有以下幾個好處:

  • 使用XML可以獲得更清晰的菜單結(jié)構(gòu)
  • 將菜單內(nèi)容與應(yīng)用的邏輯代碼分離
  • 可以使用應(yīng)用資源框架,為不同的平臺版本、屏幕尺寸創(chuàng)建最合適的菜單(如對drawable、string等系統(tǒng)資源的使用)

要定義Menu,我們首先需要在res文件夾下新建menu文件夾,它將用于存儲與Menu相關(guān)的所有XML文件。

我們可以使用<menu>、<item>、<group>三種XML元素定義Menu,下面簡單介紹一下它們:

  • <menu>是菜單項的容器。<menu>元素必須是該文件的根節(jié)點,并且能夠包含一個或多個<item>和<group>元素。
  • <item>是菜單項,用于定義MenuItem,可以嵌套<menu>元素,以便創(chuàng)建子菜單。
  • <group>是<item>元素的不可見容器(可選)??梢允褂盟鼘Σ藛雾椷M行分組,使一組菜單項共享可用性和可見性等屬性。

其中,<item>是我們主要需要關(guān)注的元素,它的常見屬性如下:

android:id:菜單項(MenuItem)的唯一標(biāo)識
android:icon:菜單項的圖標(biāo)(可選)
android:title:菜單項的標(biāo)題(必選)
android:showAsAction:指定菜單項的顯示方式。常用的有ifRoom、never、always、withText
/*
always:菜單項永遠(yuǎn)不會被收納到溢出菜單中,因此在菜單項過多的情況下可能超出菜單欄的顯示范圍。
ifRoom:在空間足夠時,菜單項會顯示在菜單欄中,否則收納入溢出菜單中。
withText:無論菜單項是否定義了icon屬性,都只會顯示它的標(biāo)題,而不會顯示圖標(biāo)。使用這種方式的菜單項默認(rèn)會被收納入溢出菜單中。
never:菜單項永遠(yuǎn)只會出現(xiàn)在溢出菜單中。*/

menu_test.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/file_delete"
        android:icon="@android:drawable/ic_delete"
        android:showAsAction="always"
        android:title="delete" />
    <item
        android:id="@+id/file_new"
        android:showAsAction="never"
        android:title="new" />
    <item
        android:id="@+id/file_save"
        android:showAsAction="never"
        android:title="save" />

    <item
        android:id="@+id/file_other"
        android:icon="@android:drawable/ic_menu_more"
        android:showAsAction="ifRoom"
        android:title="more">
        <menu>
            <item
                android:id="@+id/file_other_1"
                android:title="more1" />
            <item
                android:id="@+id/file_other_2"
                android:title="more2" />
        </menu>
    </item>
    <item
        android:id="@+id/file_more"
        android:icon="@android:drawable/ic_menu_more"
        android:showAsAction="never"
        android:title="more">
        <menu>
            <item
                android:id="@+id/file_more_1"
                android:title="more1" />
            <item
                android:id="@+id/file_more_2"
                android:title="more2" />
        </menu>
    </item>
</menu>

MainActivity.java

public class MainActivity extends Activity {
    public static final String TAG = "breeze";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG, "onCreate: ");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart: ");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume: ");
    }

    boolean shareSupport = true;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Log.i(TAG, "onCreateOptionsMenu: ");
        MenuInflater inflater = new MenuInflater(this);
        inflater.inflate(R.menu.menu_test, menu);
        // 動態(tài)添加
        if (shareSupport) {
            menu.add(Menu.NONE, Menu.FIRST, Menu.NONE, "share");
        }
        // 返回true才會顯示Menu
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.file_delete:
                break;
            case R.id.file_new:
                break;
            case Menu.FIRST:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

}
menu

點擊3個點菜單后效果如圖


test.png

關(guān)于Menu java代碼常用方法還有如下
關(guān)于Menu的幾個重要的方法,都是Activity的方法;

onCreateOptionsMenu(Menu menu)
每次Activity一創(chuàng)建就會執(zhí)行,一般只執(zhí)行一次;
onPrepareOptionsMenu(Menu menu)
每次menu被打開時,該方法就會執(zhí)行一次;
onOptionsItemSelected(MenuItem item)
每次menu菜單項被點擊時,該方法就會執(zhí)行一次;
invalidateOptionsMenu()
刷新menu里的選項里內(nèi)容,它會調(diào)用onCreateOptionsMenu(Menu menu)方法
onCreateContextMenu()
創(chuàng)建控件綁定的上下文菜單menu,根據(jù)方法里的View參數(shù)識別是哪個控件綁定
onContextItemSelected(MenuItem item)
點擊控件綁定的上下菜單menu的內(nèi)容項

onCreateOptionsMenu調(diào)用時機

I/breeze  ( 6261): onCreate: 
I/breeze  ( 6261): onStart: 
I/breeze  ( 6261): onResume: 
I/breeze  ( 6261): onCreateOptionsMenu:

Java動態(tài)創(chuàng)建Menu

該方式就無需編寫xml文件

@Override
  public boolean onCreateOptionsMenu(Menu menu) {
        Log.i(TAG, "onCreateOptionsMenu: ");
        menu.add(Menu.NONE, Menu.FIRST, Menu.NONE, "share");
        return true;
    }

Activity+Fragment構(gòu)建的選項菜單

如果Activity和Fragment都加載了Menu資源,那么這些菜單項將合并到一起。系統(tǒng)將首先顯示Activity加載的菜單項,隨后按每個Fragment添加到Activity中的順序顯示各Fragment的菜單項。如果有必要,可以使用<item>的orderInCategory屬性,對菜單項重新排序。

在Fragment中加載Menu的方式和Activity幾乎一致,同樣需要重寫onCreateOptionsMenu和onOptionsItemSelected方法。當(dāng)然,F(xiàn)ragment中的onCreateOptionsMenu方法有所不同,如下所示:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // XML形式menu,也可以采用動態(tài)添加方式
    inflater.inflate(R.menu.menu_test,menu);
}

其調(diào)用時機在onResume方法后,
需要注意,要讓Fragment中的菜單項顯示出來,還需要在Fragment中調(diào)用setHasOptionsMenu(true)方法

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 調(diào)用該方法后才會顯示Menu
    setHasOptionsMenu(true);
}

當(dāng)菜單項發(fā)生點擊事件時,如果Activity包括Fragment,則系統(tǒng)將依次為Activity和每個Fragment(按照每個Fragment的添加順序)調(diào)用onOptionsItemSelected方法,直到有一個返回結(jié)果為true或所有Fragment都調(diào)用完畢為止。因此,無論是Activity還是Fragment,onOptionsItemSelected方法中的switch語句塊中的default分支都不要直接返回true,而應(yīng)該使用return super.onOptionsItemSelected(item),避免截斷了菜單項的點擊事件.

待有時間繼續(xù)補充該文章

參考

Android Menu用法全面講解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容