Android 菜单系统分析

Android的菜单系统主要指的是ActionBar的Menu菜单。首先来看下Android菜单的使用方法:


@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.test_menu_new,menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.removeItem(R.id.aaaa);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return super.onOptionsItemSelected(item);
    }

1.        在Activity刚创建的时候会执行一次onCreateOptionsMenu方法和onPrepareOptionsMenu方法。

2.        每次点击“更多”按钮的时候,都会执行一次onPrepareOptionsMenu方法。

3.        当选中某个菜单Item的时候执行onOptionsItemSelected方法

ActionBar菜单的创建加载过程。

ActionBar及ActionBar上的菜单都是在Activity启动的时候创建的。当一个新的Activity启动的时候,ActivityManagerService调用ActivityThread的performLaunchActivity方法,此方法中会调用Activity的attach方法,为Activity初始化一些变量。在Activity的attach方法中会为每一个Activity创建一个对应的PhoneWindow对象。然后在PhoneWindow中会创建ActionBar及ActionBar相关的菜单。

Activity在启动初始化过程中会调用onCreate方法,然后调用setContentView来设置Activity的显示内容。我们就从setContentView来简单分析下Activity的menu创建过程。

Activity.setContentView
public void setContentView(View view) {
        getWindow().setContentView(view);
        initWindowDecorActionBar();
    }

Activity的setContentView方法,调用了getWindow的setContentView方法。这个getWindow获取的就是Attach方法中创建的PhoneWindow对象。然后调用initWindowDecorActionBar方法,来初始化ActionBar操作的相关方法。

PhoneWindow.setContentView
public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }

public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            ……
        } else {
            mContentParent.addView(view, params);
        }
       ……
    }

PhoneWindow的setContentView方法调用了两个参数的setContentView方法。这个方法中只保留的比较重要的和我们分析相关的代码。

    首先调用installDecor方法来创建这个Activity对应的整个Window的界面布局。然后调用mContentParent.addView方法,将自己在setContentView方法中传过来的布局文件添加到mContentParent布局中。

PhoneWindow.installDecor
private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();

            final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                    R.id.decor_content_parent);

            if (decorContentParent != null) {
                PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
                if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
                    invalidatePanelMenu(FEATURE_ACTION_BAR);
                }
            } 
        }
    }

installDecor方法主要作用是生成和设置整个phoneWindow的窗口布局文件。首先调用generateDecor方法生成一个DecorView对象。然后调用generateLayout方法来添加生成窗口的布局文件,返回了一个mContentParent对象,contentParent对象就是setContentView的时候要把设置的布局文件 添加到这个View对象中,作为这个View的子View。然后从PhoneWindow的布局文件中找到id为decor_content_parent 的View对象,decorContentParent就是PhoneWindow布局文件的根布局文件。

    这个方法两个关键点:

1.  generateLayout方法生成窗口的布局文件

2.  invalidatePanelMenu创建菜单

AA
PhoneWindow.generateLayout
protected ViewGroup generateLayout(DecorView decor) {
        ……
        int layoutResource;
        int features = getLocalFeatures();
        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
            ……
            } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
                layoutResource = a.getResourceId(
                        R.styleable.Window_windowActionBarFullscreenDecorLayout,
                        R.layout.screen_action_bar);
            } else
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值