《Android内核剖析》第8章笔记
1. 分析
1.1 主要类
1.2 主要流程
1.3 关键代码
private void openPanel(PanelFeatureState st, KeyEvent event) { // System.out.println("Open panel: isOpen=" + st.isOpen); // Already open, return if (st.isOpen) { return; } Callback cb = getCallback(); if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) { // Callback doesn't want the menu to open, reset any state closePanel(st, true); return; } final WindowManager wm = getWindowManager(); if (wm == null) { return; } // Prepare panel (should have been done before, but just in case) if (!preparePanel(st, event)) { return; } ....
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(); if (cb != null) { 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 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 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; }
根据Callback 也即Activity的onCreatePanelView()方法的返回结果, 导致preparePanel返回不同的布尔值, 最终影响openPanel()方法的执行路径 。若返回false, 表示使用完全自定义的OptionMenu视图,openPanel()直接退出;否则使用系统的OptionMenu视图。
所以, 可以重写Activity的onCreatePanelView()方法提供一个完全自定义的OptionMenu视图
2. 示例
1. Java代码。 重写Activity的onCreatePanelView()方法。
public class CustomOptionMenuActivity extends Activity { @Override public View onCreatePanelView(int featureId) { // return super.onCreatePanelView(featureId); View v = getLayoutInflater().inflate( R.layout.activity_custom_option_menu, null); v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { MyLog.i(""); Toast.makeText(CustomOptionMenuActivity.this, "text", Toast.LENGTH_SHORT).show(); CustomOptionMenuActivity.this.finish(); } }); return v; } }
2. 布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:text="TextView" android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="10dip"></TextView> </LinearLayout>
3. 截图
如上图, 点击Menu键后, 出现一个自定义OptionMenu。