標籤:安卓
dialog是應用類視窗 其子類 大多會改為子視窗
popupwindow是應用類視窗 當其顯示時會改為子視窗
contextwindow也是應用類視窗
optionMenu是應用類視窗
應用類別檢視的根視圖都是DecorView
Menu重要類介紹:
Menu: 一個interface 描述了一個菜單應該具備的操作介面 這裡的菜單是指整個菜單 而不是一個條目
MenuBuilder是其真正實現
MenuItem: 一個interface 描述一個菜單條目應該具備的操作介面 MenuItemImpl是其實現 該類中儲存的條目的資料
ContextMenuBuilder: 該類中有一個Arraylist(MenuItemImpl)變數 用於儲存整個菜單的條目資訊
拓展了MenuBuilder 增加了contextMenu的特性
MenuDialogHelper: 提供顯示menu的操作
ContextMenu顯示流程:
長按->view類的performLongClick()->showContextMenu()->調用mparent.showContextMenuForChild() 此時根視圖為(DecorView)
即 DecorView的showContextMenuForChild()->ContextMenuBuilder類的show()->在show()中調用view類的createContextMenu()方法建立詳細的條目
->最終調用MenuDialogHelper類的show()方法 完成顯示
建立optionMenu的3種方法:
當按下menu鍵時會調用phoneWindow的preparePanel方法
public final boolean preparePanel(PanelFeatureState st, KeyEvent event) { // Already prepared (isPrepared will be reset to false later) if (st.isPrepared) return true; if ((mPreparedPanel != null) && (mPreparedPanel != st)) { // Another Panel is prepared and possibly open, so close it closePanel(mPreparedPanel, false); } final Callback cb = getCallback(); //cb==activity if (cb != null) { //調用onCreatePanelView來顯示一個自訂的optionMenu st.createdPanelView = cb.onCreatePanelView(st.featureId); } if (st.createdPanelView == null) { // Init the panel state's menu--return false if init failed if (st.menu == null) { if (!initializePanelMenu(st) || (st.menu == null)) { return false; } // Call callback, and return if it doesn't want to display menu //調用activity的oncreateOptionMenu來建立一個Menu if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) { // Ditch the menu created above st.menu = null; return false; } } // Callback and return if the callback does not want to show the menu //onPreparePanel自訂optionMenu if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) { return false; } // Set the proper keymap KeyCharacterMap kmap = KeyCharacterMap.load(event != null ? event.getDeviceId() : 0); st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC; st.menu.setQwertyMode(st.qwertyMode); } // Set other state st.isPrepared = true; st.isHandled = false; mPreparedPanel = st; return true; }先看幾個概念
分析上述代碼 :可以看到有3處注釋
在這3處注釋中分別用了3種方式來建立一個menu
這裡的CallBack就是Activity (activity實現了callback介面)
1.onCreatePanelView
acitivity的onCreatePanelView方法
public View onCreatePanelView(int featureId) { return null; } st.createdPanelView = cb.onCreatePanelView(st.featureId);
通過重寫onCreatePanelView 我們可以更改createdPanelView的值 從而實現自訂optionMenu
2.cb.onCreatePanelMenu(st.featureId, st.menu)
public boolean onCreatePanelMenu(int featureId, Menu menu) { if (featureId == Window.FEATURE_OPTIONS_PANEL) { return onCreateOptionsMenu(menu); } return false; }這裡調用onCreateOptionMenu方法 也是我們建立OptionMenu最常用的方法
這裡提供了一個menu對象 讓我們來進行操作 而對於背景view則是使用預設的
再看:
if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) { // Ditch the menu created above st.menu = null; return false; }
onCreatePanelMenu預設返回值是false 在if語句中也就是true
所以執行st.menu = null;
所以我們重寫onCreatePanelMenu一定要返回ture
3.onPreparePanel
public boolean onPreparePanel(int featureId, View view, Menu menu) { if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) { boolean goforit = onPrepareOptionsMenu(menu); return goforit && menu.hasVisibleItems(); } return true; }
這裡我們直接重寫onPreparePanel 為createdPanelView(view)和menu(menu)賦值 達到自訂optionMenu的目標
android 視窗介紹