Android中menu的使用集錦

image

最近在研究關(guān)于MaterialDesign系類的內(nèi)容,在研究Toolbar和NavigationView的時(shí)候,都使用到menu的內(nèi)容。感覺自己不是很理解,可以說就是不知道,只會(huì)簡單的寫一個(gè)menu其他的什么都不會(huì)了。所以總結(jié)一下,希望對大家有幫助?。。?/p>

本文會(huì)講解的知識點(diǎn)

  • menu的使用
  • menu的屬性說明
  • menu的使用注意事項(xiàng)

1. menu的使用

首先說明一下menu的存放位置,在創(chuàng)建項(xiàng)目的時(shí)候,是沒有menu文件夾的,所以這里你要自己創(chuàng)建一個(gè)menu文件夾,然后新建一個(gè)menu文件。具體位置看下面這張圖就可以了(因?yàn)檫@張圖設(shè)置了相應(yīng)的樣式,所以彈出來的popup有一個(gè)背景色)!

menu文件的位置

下面我們來介紹關(guān)于menu文件怎么寫,以及各個(gè)屬性的含義

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

    <item
        android:id="@+id/menu_search"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="搜索"
        app:actionViewClass="android.widget.SearchView"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/menu_cycling"
        android:icon="@mipmap/ic_directions_bike_white_24dp"
        android:title="去知乎的Toolbar"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/menu_other"
        android:title="去網(wǎng)易云音樂的ToolBar"
        app:showAsAction="never" />

    <item
        android:id="@+id/menu_more"
        android:title="更多">
        <menu>
            <item
                android:id="@+id/menu_more1"
                android:title="更多1" />
            <item
                android:id="@+id/menu_more2"
                android:title="更多2" />
            <item
                android:id="@+id/menu_more3"
                android:title="更多3" />
        </menu>
    </item>

</menu>

這是一個(gè)比較復(fù)雜的menu文件了,對于一般的menu不會(huì)有下面更多的那個(gè)item。還是先看一下效果吧!

多層的menu文件的顯示

看了效果之后,我們就很好理解其中的屬性了,這里先解釋一下相應(yīng)的menu標(biāo)簽的屬性值:

2. menu的屬性說明

2.1 item的屬性說明

這里面的屬性很多,但是個(gè)人覺得有很多用不上,列出來的都是一些常用的屬性。

  • android:id 控件的ID
  • android:icon 空間的圖標(biāo)(這里如果顯示在Toolbar上面,會(huì)顯示圖片,在溢出菜單里面的話會(huì)只顯示文字)
  • android:title 顯示的標(biāo)題(也就是條目的內(nèi)容)
  • app:actionViewClass 引入一個(gè)View(這個(gè)是在實(shí)現(xiàn)搜索的時(shí)候用到的)
  • app:showAsAction 顯示方式
    • ifRoom 如果有空間的話,會(huì)顯示在ToolBar上,當(dāng)空間不足的時(shí)候會(huì)顯示在列表中
    • always 一直顯示在ToolBar上(如果沒有空間的話,還是會(huì)顯示在列表中,按先后順序排列的)
    • collapseActionView (一般要配合ifRoom一起使用)聲明這個(gè)操作視窗應(yīng)該被折疊到一個(gè)按鈕中,當(dāng)用戶選擇這個(gè)按鈕時(shí),這個(gè)操作視窗展開。這個(gè)屬性主要是實(shí)現(xiàn)自意義溢出菜單的??梢栽谒睦锩嬖O(shè)置一些item從而實(shí)現(xiàn)溢出菜單(這個(gè)自定義的溢出菜單和默認(rèn)的溢出菜單唯一的區(qū)別就是它可以顯示圖標(biāo))
    • never 不會(huì)顯示在Toolbar上面,會(huì)顯示在列列表中
    • withText 表示顯示的時(shí)候如果空間足夠,會(huì)顯示menu的title。但是我試了試沒看到,還請知道的大神告知一聲!
  • android:titleCondensed 當(dāng)你設(shè)置的內(nèi)容過長的時(shí)候,可以使用這個(gè)屬性進(jìn)行簡短的說明
  • android:onClick 和View的onClick方法類似,設(shè)置一個(gè)點(diǎn)擊事件
  • android:checkable 菜單是否可以復(fù)選,如果可以復(fù)選的話設(shè)置成true
  • android:checked 菜單是否可以被選中,如果可以被選中的話設(shè)置成true
  • android:visible 菜單是否顯示
  • android:enabled 菜單項(xiàng)目是否可用,如果可用為true。主要是用在自定義溢出菜單的時(shí)候,是否可以進(jìn)行相應(yīng)的相應(yīng)。
  • android:orderInCategory 菜單的優(yōu)先級,整數(shù)類型,數(shù)字越小越靠前

2.2 group的屬性說明

主要是一個(gè)組的屬性,和RadioGroup的樣式類似,主要是實(shí)現(xiàn)復(fù)選的!里面的一些屬性和上面是類似的,這里主要說明一個(gè)屬性

  • android:checkableBeharior 設(shè)置復(fù)選行為的類型
    • none 沒有可復(fù)選性
    • all 組內(nèi)的所有的項(xiàng)目都可以被復(fù)選(使用復(fù)選框)
    • single 僅有一個(gè)項(xiàng)目能夠被復(fù)選(使用單選按鈕)

下面是關(guān)于group標(biāo)簽的使用

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/app_bar_search"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="Search"
        app:actionViewClass="android.widget.SearchView"
        app:showAsAction="always" />
    <item
        android:id="@+id/menu_delete"
        android:icon="@mipmap/ic_delete"
        android:title="刪除"
        app:showAsAction="always|collapseActionView">

        <menu>
            <group android:checkableBehavior="all">
                <item android:title="group1" />
                <item android:title="group2" />
                <item android:title="group3" />
            </group>
        </menu>
    </item>
    <item
        android:id="@+id/menu_setting"
        android:icon="@mipmap/ic_delete"
        android:title="設(shè)置"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/menu_other"
        android:icon="@mipmap/ic_delete"
        android:title="不知道什么"
        app:showAsAction="ifRoom" />
</menu>

這里就是通過自定義溢出菜單展示的group,具體效果看下面這張圖

group的展示

設(shè)置menu二級菜單的時(shí)候(無論是自定義還是系統(tǒng)的),前一級標(biāo)簽的文字顏色是黑色的,這個(gè)目前還沒有找到好的解決方案,希望知道的給留個(gè)言?。?!謝謝

3. menu的使用注意事項(xiàng)

這里我主要像說明一下我在開發(fā)中遇到的關(guān)于menu的一些問題

  • Fragment中怎么顯示menu?
  • Activity和Fragment同時(shí)使用menu會(huì)怎樣顯示?
  • Activity和Fragment同時(shí)處理點(diǎn)擊事件怎么相應(yīng)?
  • menu的怎么動(dòng)態(tài)改變?
  • 多個(gè)Activity同時(shí)使用一個(gè)menu怎么簡化操作?

這些問題,在平時(shí)的開發(fā)中,相信很多人都不會(huì)注意到!所以這里有必要和大家分享一下相關(guān)的內(nèi)容。

3.1 Fragment中怎么顯示menu?

Fragment中顯示menu文件和Activity中是類似的,但是必須在掛在View之前添加setHasOptionsMenu(true);這句代碼(基本上都是加載onCreat()上面),否則顯示不出來的。。。

public class Main1Fragment extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_main1, container, false);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_main_fragment1, menu);
    }
}

上面這段代碼就是Fragment中顯示menu的方法!

3.2 Activity和Fragment同時(shí)使用menu會(huì)怎樣顯示?

是不是覺得很奇怪的問題,你的答案是什么?是不是變得模棱兩可了,其實(shí)有的面試官很關(guān)注這些細(xì)節(jié)。答案就是疊加顯示,怎么個(gè)疊加顯示呢?一個(gè)簡單的說明,你在Activity中添加了一個(gè)設(shè)置的menu條目,如果你在Fragment中也寫了一個(gè),那么menu上會(huì)新增一個(gè)Fragment的menu文件。


就像這樣

3.3 Activity和Fragment同時(shí)處理點(diǎn)擊事件怎么相應(yīng)?

有的人可能會(huì)問了,那點(diǎn)擊事件怎么處理呢?其實(shí)處理起來很簡單,就是在onOptionsItemSelected處理相應(yīng)的點(diǎn)擊事件。但是有一個(gè)點(diǎn)需要注意,就是Activity的onOptionsItemSelected方法的返回值!默認(rèn)的情況下應(yīng)該返回super.onOptionsItemSelected(item)這個(gè),防止處理了事件之后,F(xiàn)ragment收不到相應(yīng)的點(diǎn)擊事件!

  • Activity的onOptionsItemSelected方法:
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_setting:
                Log.e(TAG, "onOptionsItemSelected: setting");
                return true;
            case R.id.menu_other:
                Log.e(TAG, "onOptionsItemSelected: other" );
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
  • Fragment的onOptionsItemSelected方法:
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.fragment1:
                Log.e(TAG, "onOptionsItemSelected: fragment1" );
                return true;
            case R.id.fragment2:
                Log.e(TAG, "onOptionsItemSelected: fragment2" );
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

這樣所有的點(diǎn)擊事件就能得到相應(yīng)的響應(yīng)了。

3.4 menu的怎么動(dòng)態(tài)改變?

有的人可能說動(dòng)態(tài)的刷新了menu但是卻沒有成功,其實(shí)是沒有調(diào)用invalidateOptionsMenu();通知menu刷新的方法造成的。下面我們來看看menu刷新的代碼:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.fragment1:
                Log.e(TAG, "onOptionsItemSelected: fragment1");
                isRefeesh = true;
                getActivity().invalidateOptionsMenu();
                return true;
            case R.id.fragment2:
                Log.e(TAG, "onOptionsItemSelected: fragment2");
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        MenuItem item = menu.findItem(R.id.fragment1);
        if (isRefeesh) {
            item.setTitle("刷新后的fragment1");
        } else {
            item.setTitle(item.getTitle());
        }
    }

這里說一下相應(yīng)的邏輯,當(dāng)調(diào)用invalidateOptionsMenu();的時(shí)候會(huì)重走onPrepareOptionsMenu這個(gè)方法,這里我用了一個(gè)標(biāo)識去標(biāo)記是否刷新,為什么會(huì)有這個(gè)標(biāo)識呢?因?yàn)?code>onPrepareOptionsMenu準(zhǔn)備menu的時(shí)候調(diào)用,所以剛一進(jìn)來的時(shí)候就會(huì)被調(diào)用一次,點(diǎn)擊后還會(huì)調(diào)用一次。

3.5 多個(gè)Activity同時(shí)使用一個(gè)menu怎么簡化操作?

這個(gè)相當(dāng)于繼承的關(guān)系。其實(shí)這個(gè)問題也是相應(yīng)的疊加問題,只要你記住menu是可以疊加的就可以。只要在你的onCreateOptionsMenu方法中加載父類的menu就可以了,像下面面這樣!

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);//調(diào)用這一句保證父類的菜單項(xiàng)可以正常加載
    getMenuInflater().inflate(R.menu.menu_main_fragment,menu);//加載子類自己的菜單項(xiàng)
    return true;
}

基本上關(guān)于menu的使用就這些了,總結(jié)的可能還會(huì)有不到位的地方,如果你還有關(guān)于menu的使用問題,可以給我留言。

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

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,175評論 25 708
  • 我讀書挺慢的,三天讀完馮唐的《三十六大》,還是在學(xué)院辦公室做助管的時(shí)候讀完的,辦公室沒有事情的時(shí)候,我就拿出綠色封...
    李旭洋閱讀 421評論 0 0
  • 我反復(fù)推敲 自己來的早還是晚 亦或是正當(dāng)時(shí) 在它盛妝將卸時(shí)到場 我早忘了將它放在夢里 兀自地它開在夢外 謝場也在夢...
    永遠(yuǎn)的清湄閱讀 271評論 4 2
  • 連續(xù)五天跟隨長安老師的阿奴薩拉瑜伽習(xí)練集訓(xùn)結(jié)束了。作為一個(gè)有四五年瑜伽習(xí)練經(jīng)驗(yàn)的老人來說,這是一個(gè)從內(nèi)進(jìn)行自我打破...
    木魚78閱讀 289評論 1 2
  • 陽光燦爛的日子 風(fēng)兒輕佛臉頰 樹上的鳥兒 還在嘰嘰渣渣 樹下的老人 睡得正香 一絲微笑還掛在嘴角 夢中 又至除夕 ...
    幽幽墨香閱讀 190評論 4 5

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