Android動(dòng)態(tài)更新Menu菜單的實(shí)現(xiàn)過程
1. 需求描述
Android Menu菜單是比較常見的功能,在ActionBar or ToolBar上顯示,點(diǎn)擊更多(3個(gè)點(diǎn)),會(huì)有下拉列表菜單展示, 在工作項(xiàng)目中有個(gè)小需求改動(dòng): 在 ToolBar上添加一個(gè)圖標(biāo),點(diǎn)擊后會(huì)切換圖標(biāo)狀態(tài),界面也會(huì)顯示對(duì)應(yīng)內(nèi)容,這也是本篇文章要講的是如何動(dòng)態(tài)更新Menu菜單。
首先,我們來(lái)看看效果圖:
1. 當(dāng)點(diǎn)擊網(wǎng)格圖標(biāo)時(shí),顯示為網(wǎng)格模式

2. 當(dāng)點(diǎn)擊列表圖標(biāo)時(shí),顯示為列表模式

3. 點(diǎn)擊更多圖標(biāo)時(shí),顯示更多菜單列表:設(shè)置 關(guān)于 測(cè)試

2. 基礎(chǔ)知識(shí)
在寫代碼之前,先來(lái)復(fù)習(xí)一下Menu的基礎(chǔ)知識(shí),具體可以看官方文檔:Menus | Android Developers
菜單xml編寫例子:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.menutest.MainActivity">
<item
android:id="@+id/sub_menu_grid"
android:title="網(wǎng)格視圖"
android:icon="@drawable/ic_menu_view_grid"
app:showAsAction="always"/>
<item
android:id="@+id/sub_menu_list"
android:title="列表視圖"
android:icon="@drawable/ic_menu_view_list"
app:showAsAction="always"/>
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="設(shè)置"
app:showAsAction="never" />
<item
android:id="@+id/action_about"
android:orderInCategory="200"
android:title="關(guān)于"
app:showAsAction="never" />
<item
android:id="@+id/action_test"
android:orderInCategory="300"
android:title="測(cè)試"
app:showAsAction="never" />
</menu><item>是我們主要需要關(guān)注的元素,它的常見屬性如下:
android:id: 菜單項(xiàng)(MenuItem)的唯一標(biāo)識(shí)(必須定義)
android:icon: 菜單項(xiàng)的圖標(biāo)(可選)
android:title: 菜單項(xiàng)的標(biāo)題(必選)
android:showAsAction:指定菜單項(xiàng)的顯示方式。常用的有ifRoom、never、always、withText,多個(gè)屬性值之間可以使用|隔開。
指定菜單的顯示方式:
always:菜單項(xiàng)永遠(yuǎn)不會(huì)被收納到溢出菜單中,因此在菜單項(xiàng)過多的情況下可能超出菜單欄的顯示范圍。
ifRoom:在空間足夠時(shí),菜單項(xiàng)會(huì)顯示在菜單欄中,否則收納入溢出菜單中。
withText:無(wú)論菜單項(xiàng)是否定義了icon屬性,都只會(huì)顯示它的標(biāo)題,而不會(huì)顯示圖標(biāo)。使用這種方式的菜單項(xiàng)默認(rèn)會(huì)被收納入溢出菜單中。
never:菜單項(xiàng)永遠(yuǎn)只會(huì)出現(xiàn)在溢出菜單中。
我們通過上面的3張圖片,在Toolbar上面顯示有兩類菜單:
1. 比如網(wǎng)格和列表菜單,在菜單欄上定義為一直顯示(always),我們稱它為常駐菜單
2. 另一種會(huì)被集中放置到溢出菜單中(就是菜單欄右側(cè)的3個(gè)小點(diǎn)圖標(biāo)圖標(biāo))
3. 菜單加載
菜單加載,有兩個(gè)相關(guān)API
1. onCreateOptionsMenu(Menu menu)
此方法在初次加載菜單時(shí),會(huì)調(diào)用一次。
2. onPrepareOptionsMenu(Menu menu)
此方法應(yīng)用場(chǎng)景:在運(yùn)行時(shí)更改菜單項(xiàng),我們看看官網(wǎng)的描述:
在運(yùn)行時(shí)修改的選項(xiàng)菜單:
系統(tǒng)調(diào)用onCreateOptionsMenu方法后,將保留創(chuàng)建的Menu實(shí)例。除非菜單由于某些原因而失效,否則不會(huì)再次調(diào)用onCreateOptionsMenu。因此,我們只應(yīng)該使用onCreateOptionsMenu來(lái)創(chuàng)建初始菜單狀態(tài),而不應(yīng)使用它在Activity生命周期中對(duì)菜單執(zhí)行任何更改。
如果需要根據(jù)在Activity生命周期中發(fā)生的某些事件修改選項(xiàng)菜單,則應(yīng)該通過onPrepareOptionsMenu方法實(shí)現(xiàn)。這個(gè)方法的參數(shù)中有一個(gè)Menu對(duì)象(即舊的Menu對(duì)象),我們可以使用它對(duì)菜單執(zhí)行修改,如添加、移除、啟用或禁用菜單項(xiàng)。(Fragment同樣提供onPrepareOptionsMenu方法,只是不需要提供返回值)
需要注意:在Android 3.0及更高版本中,當(dāng)菜單項(xiàng)顯示在應(yīng)用欄中時(shí),選項(xiàng)菜單被視為始終處于打開狀態(tài),說的就是常駐菜單。發(fā)生事件時(shí),如果要執(zhí)行菜單更新,則必須調(diào)用 invalidateOptionsMenu來(lái)請(qǐng)求系統(tǒng)調(diào)用onPrepareOptionsMenu方法。
對(duì)于上句話我的理解如下:
1. 對(duì)于常駐菜單,如果你想動(dòng)態(tài)修改菜單的話,就必須調(diào)用 invalidateOptionsMenu() 方法去更新,為什么呢? 因?yàn)檎{(diào)用 invalidateOptionsMenu方法后,會(huì)重新執(zhí)行一遍 onCreateOptionsMenu 和 onPrepareOptionsMenu這兩個(gè)方法。
2. 對(duì)于溢出菜單,如果你想動(dòng)態(tài)修改菜單的話,只需要在onPrepareOptionsMenu方法中實(shí)現(xiàn)即可,為什么呢?
當(dāng)你點(diǎn)擊 更多(3個(gè)小點(diǎn))圖標(biāo)的時(shí)候,就會(huì)回調(diào)onPrepareOptionsMenu方法
4. 需求實(shí)現(xiàn)
有了上面理論做支持,具體結(jié)合需求,網(wǎng)格和列表菜單屬于常駐菜單,所以必須先要調(diào)用invalidateOptionsMenu()方法,然后在onPrepareOptionsMenu去寫動(dòng)態(tài)更新狀態(tài)的代碼
圖三中,關(guān)于屬于溢出菜單,需求: 關(guān)于 菜單不能點(diǎn)擊,所以也是在onPrepareOptionsMenu中去寫動(dòng)態(tài)更新狀態(tài)的代碼
好了,我把代碼展示出來(lái):
public class MainActivity extends AppCompatActivity {
//默認(rèn)為網(wǎng)格模式
private boolean isShowGridModeIcon = true;
//網(wǎng)格菜單 和 列表菜單
private MenuItem gridMenuItem;
private MenuItem listMenuItem;
//用字符串來(lái)表示當(dāng)前的文件列表顯示模式
private TextView viewModeStatus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewModeStatus = findViewById(R.id.textview_refresh);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
Log.e("test", "=====MenuTest onCreateOptionsMenu=====");
gridMenuItem = menu.findItem(R.id.sub_menu_grid);
listMenuItem = menu.findItem(R.id.sub_menu_list);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
Log.e("test", "=====MenuTest onPrepareOptionsMenu=xxxx====");
MenuItem aboutMenuItem = menu.findItem(R.id.action_about);
// (3個(gè)點(diǎn))【更多】菜單中把 關(guān)于 設(shè)置為不可點(diǎn)擊
aboutMenuItem.setEnabled(false);
if (isShowGridModeIcon) {
gridMenuItem.setVisible(true);
listMenuItem.setVisible(false);
viewModeStatus.setText("當(dāng)前為網(wǎng)格模式");
} else {
gridMenuItem.setVisible(false);
listMenuItem.setVisible(true);
viewModeStatus.setText("當(dāng)前為列表模式");
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
Log.e("test", "=====MenuTest onOptionsItemSelected= sssss ====");
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} else if (id == R.id.sub_menu_grid) {
/*1. 點(diǎn)擊網(wǎng)格圖標(biāo),界面中文件布局顯示變成網(wǎng)格模式*/
//偽代碼:setViewMode(State.MODE_GRID);
isShowGridModeIcon = false;
/*2. 圖標(biāo)變成切換list圖標(biāo)*/
invalidateOptionsMenu();
} else if (id == R.id.sub_menu_list) {
/*1.點(diǎn)擊列表圖標(biāo),界面中文件布局顯示變成列表模式*/
//偽代碼:setViewMode(State.MODE_LIST);
isShowGridModeIcon = true;
/*2. 圖標(biāo)變成切換grid圖標(biāo)*/
invalidateOptionsMenu();
}
return super.onOptionsItemSelected(item);
}
}代碼中加了打印log
1. 在桌面上啟動(dòng)apk的時(shí)候,打印log如下:
21900 21900 E test : =====MenuTest onCreateOptionsMenu===== 21900 21900 E test : =====MenuTest onPrepareOptionsMenu=xxxx====
2. 點(diǎn)擊網(wǎng)格模式菜單時(shí),打印log如下:
21900 21900 E test : =====MenuTest onOptionsItemSelected= sssss ==== 21900 21900 E test : =====MenuTest onCreateOptionsMenu===== 21900 21900 E test : =====MenuTest onPrepareOptionsMenu=xxxx====
如上分析,在onOptionsItemSelected方法中點(diǎn)擊響應(yīng)時(shí),調(diào)用了invalidateOptionsMenu方法,所以會(huì)重新走一遍onCreateOptionsMenu, onPrepareOptionsMenu。
3. 點(diǎn)擊(3個(gè)點(diǎn))更多菜單時(shí),打印log如下:
21900 21900 E test : =====MenuTest onPrepareOptionsMenu=xxxx====
如上分析, 對(duì)于溢出菜單類型,點(diǎn)擊更多菜單時(shí),只會(huì)回調(diào)onPrepareOptionsMenu方法
5. 總結(jié)
本篇文章講解了動(dòng)態(tài)菜單更新顯示的過程,也是對(duì)menu菜單的一個(gè)小結(jié),對(duì)于同類需求,可以仿照此demo,整個(gè)Demo代碼我上傳到這里:Android動(dòng)態(tài)更新Menu菜單
到此這篇關(guān)于Android動(dòng)態(tài)更新Menu菜單的文章就介紹到這了,更多相關(guān)Android動(dòng)態(tài)更新Menu菜單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android開發(fā)中WebView的簡(jiǎn)單使用小結(jié)
WebView(網(wǎng)絡(luò)視圖)能加載顯示網(wǎng)頁(yè),可以將其視為一個(gè)瀏覽器。它使用了WebKit渲染引擎加載顯示網(wǎng)頁(yè)。下面這篇文章給大家總結(jié)了Android中WebView的簡(jiǎn)單使用,有需要的可以參考借鑒。2016-09-09
雙緩沖技術(shù)實(shí)現(xiàn)Android 畫板應(yīng)用
這篇文章主要介紹了Android 采用雙緩存技術(shù)實(shí)現(xiàn)畫板應(yīng)用的相關(guān)資料,并附有代碼實(shí)例,有需要的小伙伴可以參考下2016-07-07
Android 滑動(dòng)定位和吸附懸停效果實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 滑動(dòng)定位和吸附懸停效果實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-08-08
Android App中使用SurfaceView制作多線程動(dòng)畫的實(shí)例講解
這篇文章主要介紹了Android App中使用SurfaceView制作多線程動(dòng)畫的實(shí)例講解,SurfaceView經(jīng)常被用來(lái)制作游戲中的動(dòng)畫,不過同時(shí)要注意畫面閃爍的問題,需要的朋友可以參考下2016-04-04
Android開發(fā)之圖形圖像與動(dòng)畫(四)AnimationListener簡(jiǎn)介
就像Button控件有監(jiān)聽器一樣,動(dòng)畫效果也有監(jiān)聽器,只需要實(shí)現(xiàn)AnimationListener就可以實(shí)現(xiàn)對(duì)動(dòng)畫效果的監(jiān)聽,感興趣的朋友可以了解下啊,希望本文對(duì)你有所幫助2013-01-01
Android中外接鍵盤的檢測(cè)的實(shí)現(xiàn)
這篇文章主要介紹了Android中外接鍵盤的檢測(cè)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Android ScrollView實(shí)現(xiàn)下拉彈回動(dòng)畫效果
這篇文章主要為大家詳細(xì)介紹了Android ScrollView實(shí)現(xiàn)下拉彈回動(dòng)畫效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08

