Android動態(tài)更新Menu菜單的實現(xiàn)過程
1. 需求描述
Android Menu菜單是比較常見的功能,在ActionBar or ToolBar上顯示,點擊更多(3個點),會有下拉列表菜單展示, 在工作項目中有個小需求改動: 在 ToolBar上添加一個圖標,點擊后會切換圖標狀態(tài),界面也會顯示對應內(nèi)容,這也是本篇文章要講的是如何動態(tài)更新Menu菜單。
首先,我們來看看效果圖:
1. 當點擊網(wǎng)格圖標時,顯示為網(wǎng)格模式
2. 當點擊列表圖標時,顯示為列表模式
3. 點擊更多圖標時,顯示更多菜單列表:設置 關于 測試
2. 基礎知識
在寫代碼之前,先來復習一下Menu的基礎知識,具體可以看官方文檔: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="設置" app:showAsAction="never" /> <item android:id="@+id/action_about" android:orderInCategory="200" android:title="關于" app:showAsAction="never" /> <item android:id="@+id/action_test" android:orderInCategory="300" android:title="測試" app:showAsAction="never" /> </menu>
<item>是我們主要需要關注的元素,它的常見屬性如下:
android:id: 菜單項(MenuItem)的唯一標識(必須定義)
android:icon: 菜單項的圖標(可選)
android:title: 菜單項的標題(必選)
android:showAsAction:指定菜單項的顯示方式。常用的有ifRoom、never、always、withText,多個屬性值之間可以使用|隔開。
指定菜單的顯示方式:
always
:菜單項永遠不會被收納到溢出菜單中,因此在菜單項過多的情況下可能超出菜單欄的顯示范圍。
ifRoom
:在空間足夠時,菜單項會顯示在菜單欄中,否則收納入溢出菜單中。
withText
:無論菜單項是否定義了icon
屬性,都只會顯示它的標題,而不會顯示圖標。使用這種方式的菜單項默認會被收納入溢出菜單中。
never
:菜單項永遠只會出現(xiàn)在溢出菜單中。
我們通過上面的3張圖片,在Toolbar上面顯示有兩類菜單:
1. 比如網(wǎng)格和列表菜單,在菜單欄上定義為一直顯示(always
),我們稱它為常駐菜單
2. 另一種會被集中放置到溢出菜單中(就是菜單欄右側(cè)的3個小點圖標圖標)
3. 菜單加載
菜單加載,有兩個相關API
1. onCreateOptionsMenu(Menu menu)
此方法在初次加載菜單時,會調(diào)用一次。
2. onPrepareOptionsMenu(Menu menu)
此方法應用場景:在運行時更改菜單項,我們看看官網(wǎng)的描述:
在運行時修改的選項菜單:
系統(tǒng)調(diào)用onCreateOptionsMenu方法后,將保留創(chuàng)建的Menu實例。除非菜單由于某些原因而失效,否則不會再次調(diào)用onCreateOptionsMenu。因此,我們只應該使用onCreateOptionsMenu來創(chuàng)建初始菜單狀態(tài),而不應使用它在Activity生命周期中對菜單執(zhí)行任何更改。
如果需要根據(jù)在Activity生命周期中發(fā)生的某些事件修改選項菜單,則應該通過onPrepareOptionsMenu方法實現(xiàn)。這個方法的參數(shù)中有一個Menu對象(即舊的Menu對象),我們可以使用它對菜單執(zhí)行修改,如添加、移除、啟用或禁用菜單項。(Fragment同樣提供onPrepareOptionsMenu方法,只是不需要提供返回值)
需要注意:在Android 3.0及更高版本中,當菜單項顯示在應用欄中時,選項菜單被視為始終處于打開狀態(tài),說的就是常駐菜單。發(fā)生事件時,如果要執(zhí)行菜單更新,則必須調(diào)用 invalidateOptionsMenu來請求系統(tǒng)調(diào)用onPrepareOptionsMenu方法。
對于上句話我的理解如下:
1. 對于常駐菜單,如果你想動態(tài)修改菜單的話,就必須調(diào)用 invalidateOptionsMenu() 方法去更新,為什么呢? 因為調(diào)用 invalidateOptionsMenu方法后,會重新執(zhí)行一遍 onCreateOptionsMenu 和 onPrepareOptionsMenu這兩個方法。
2. 對于溢出菜單,如果你想動態(tài)修改菜單的話,只需要在onPrepareOptionsMenu方法中實現(xiàn)即可,為什么呢?
當你點擊 更多(3個小點)圖標的時候,就會回調(diào)onPrepareOptionsMenu方法
4. 需求實現(xiàn)
有了上面理論做支持,具體結(jié)合需求,網(wǎng)格和列表菜單屬于常駐菜單,所以必須先要調(diào)用invalidateOptionsMenu()方法,然后在onPrepareOptionsMenu去寫動態(tài)更新狀態(tài)的代碼
圖三中,關于屬于溢出菜單,需求: 關于 菜單不能點擊,所以也是在onPrepareOptionsMenu中去寫動態(tài)更新狀態(tài)的代碼
好了,我把代碼展示出來:
public class MainActivity extends AppCompatActivity { //默認為網(wǎng)格模式 private boolean isShowGridModeIcon = true; //網(wǎng)格菜單 和 列表菜單 private MenuItem gridMenuItem; private MenuItem listMenuItem; //用字符串來表示當前的文件列表顯示模式 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個點)【更多】菜單中把 關于 設置為不可點擊 aboutMenuItem.setEnabled(false); if (isShowGridModeIcon) { gridMenuItem.setVisible(true); listMenuItem.setVisible(false); viewModeStatus.setText("當前為網(wǎng)格模式"); } else { gridMenuItem.setVisible(false); listMenuItem.setVisible(true); viewModeStatus.setText("當前為列表模式"); } 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. 點擊網(wǎng)格圖標,界面中文件布局顯示變成網(wǎng)格模式*/ //偽代碼:setViewMode(State.MODE_GRID); isShowGridModeIcon = false; /*2. 圖標變成切換list圖標*/ invalidateOptionsMenu(); } else if (id == R.id.sub_menu_list) { /*1.點擊列表圖標,界面中文件布局顯示變成列表模式*/ //偽代碼:setViewMode(State.MODE_LIST); isShowGridModeIcon = true; /*2. 圖標變成切換grid圖標*/ invalidateOptionsMenu(); } return super.onOptionsItemSelected(item); } }
代碼中加了打印log
1. 在桌面上啟動apk的時候,打印log如下:
21900 21900 E test : =====MenuTest onCreateOptionsMenu===== 21900 21900 E test : =====MenuTest onPrepareOptionsMenu=xxxx====
2. 點擊網(wǎng)格模式菜單時,打印log如下:
21900 21900 E test : =====MenuTest onOptionsItemSelected= sssss ==== 21900 21900 E test : =====MenuTest onCreateOptionsMenu===== 21900 21900 E test : =====MenuTest onPrepareOptionsMenu=xxxx====
如上分析,在onOptionsItemSelected方法中點擊響應時,調(diào)用了invalidateOptionsMenu方法,所以會重新走一遍onCreateOptionsMenu, onPrepareOptionsMenu。
3. 點擊(3個點)更多菜單時,打印log如下:
21900 21900 E test : =====MenuTest onPrepareOptionsMenu=xxxx====
如上分析, 對于溢出菜單類型,點擊更多菜單時,只會回調(diào)onPrepareOptionsMenu方法
5. 總結(jié)
本篇文章講解了動態(tài)菜單更新顯示的過程,也是對menu菜單的一個小結(jié),對于同類需求,可以仿照此demo,整個Demo代碼我上傳到這里:Android動態(tài)更新Menu菜單
到此這篇關于Android動態(tài)更新Menu菜單的文章就介紹到這了,更多相關Android動態(tài)更新Menu菜單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android開發(fā)中WebView的簡單使用小結(jié)
WebView(網(wǎng)絡視圖)能加載顯示網(wǎng)頁,可以將其視為一個瀏覽器。它使用了WebKit渲染引擎加載顯示網(wǎng)頁。下面這篇文章給大家總結(jié)了Android中WebView的簡單使用,有需要的可以參考借鑒。2016-09-09Android App中使用SurfaceView制作多線程動畫的實例講解
這篇文章主要介紹了Android App中使用SurfaceView制作多線程動畫的實例講解,SurfaceView經(jīng)常被用來制作游戲中的動畫,不過同時要注意畫面閃爍的問題,需要的朋友可以參考下2016-04-04Android開發(fā)之圖形圖像與動畫(四)AnimationListener簡介
就像Button控件有監(jiān)聽器一樣,動畫效果也有監(jiān)聽器,只需要實現(xiàn)AnimationListener就可以實現(xiàn)對動畫效果的監(jiān)聽,感興趣的朋友可以了解下啊,希望本文對你有所幫助2013-01-01Android ScrollView實現(xiàn)下拉彈回動畫效果
這篇文章主要為大家詳細介紹了Android ScrollView實現(xiàn)下拉彈回動畫效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08