美文网首页
WindowInsets和StatusBar

WindowInsets和StatusBar

作者: 土豆肉多 | 来源:发表于2016-12-19 17:41 被阅读0次

    WindowInsets流程:

    setContentView过程可以分为两部分,一部分是构建DecorView布局,一部分是将布局添加到window中。主要看添加到window流程:ActivityThread.handleResumeActivity-WindowManager.addView-WIndowManagerImpl.addView-WindowManagerGloble.addView-ViewRootImpl.setView-.requestLayout-.scheduleTraversals-.TraversalRunnable-.doTraversal-.performTraversals-.dispatchApplyInsets(View host)-host.dispatchApplyWindowInsets(host其实就是PhoneWindow中的DecorView),说明一下,performTranversals方法依次执行dispatchApplyInsets、performMeasure、performLayout和performDraw,最终完成View的绘制流程.
    接下来就是View和ViewGroup层次的WindowInsets调用流程了,由上面可知最后调用DecorView.dispatchApplyWindowInsets,而它直接调用ViewGroup的dispatchApplyWindowInsets,因为DecorView、FrameLayout都没有重写dispatchApplyWindowInsets方法
    <pre>
    @Override
    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
    insets = super.dispatchApplyWindowInsets(insets);
    if (!insets.isConsumed()) {
    final int count = getChildCount();
    for (int i = 0; i < count; i++) {
    insets = getChildAt(i).dispatchApplyWindowInsets(insets);
    if (insets.isConsumed()) {
    break;
    }
    }
    }
    return insets;
    }
    </pre>
    开头就直接调用了View的dispatchApplyWindowInsets处理insets,然后直接判断是否消费,如果没有消费就依次分发给child,直到有child消费insets就退出,下面先看View的dispatchApplyWindowInsets:
    <pre>
    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
    try {
    //将PLAGS3_APPLYING_INSETS注入mPrivateFlag3
    mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
    if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
    return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
    } else {
    return onApplyWindowInsets(insets);
    }
    } finally {
    //将PLAGS3_APPLYING_INSETS移除mPrivateFlag3
    mPrivateFlag3 &= ~PFLAG3_APPLYING_INSETS;
    }
    </pre>
    如果向View注册了OnApplyWindowInsetsListener监听器,就直接用监听器截取Insets操作返回,否则执行onApplyWindowInsets方法,因为DecorView没有注册监听器但重写了onApplyWindowInsets方法,所以执行DecorView的onApplyWindowInsets:
    <pre>
    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
    ...
    insets = updateColorViews(insets, true/animate/);
    insets = updateStatusGuard(insets);
    updateNavigationGuard(insets);
    ...
    return insets
    }
    </pre>
    在updateColorViews方法中,执行了两次updateColorViewInt方法,第一次传入的参数是mNavigationColorViewState,第二次传入mStatusColorViewState,代码如下:
    <pre>
    private WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
    ......
    updateColorViewInt(mNavigationColorViewState, sysUiVisibility, mNavigationBarColor, navBarSize, navBarToRightEdge, 0 /rightInset/, animate && !disallowAnimate);
    ......
    updateColorViewInt(mStatusColorViewState, sysUiVisibility, mStatusBarColor, mLastTopInset, false /matchVertical/, statusBarRightInset, animate && !disallowAnimate);
    }
    </pre>
    结合上面传入参数的名字,能够看出这段代码就是向DecorView中添加窗口顶部的StatusBar状态栏(显示电量、手机信号)的占位View和底部NavigationBar导航栏(三个大按钮的虚拟栏)的占位View,因为他们只是添加一个设置了背景色的View,所以只是占位用。代码如下:
    <pre>
    private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color, int size, boolean verticalBar, int rightMargin, boolean animate) {
    ......
    state.view = view = new View(mContext);
    view.setBackgroundColor(color);
    view.setTransitionName(state.transitionName);
    view.setId(state.id);
    visibilityChanged = true;
    view.setVisibility(INVISIBLE);
    state.targetVisibility = VISIBLE;
    LayoutParams lp = new LayoutParams(resolvedWidth, resolvedHeight, resolvedGravity);
    lp.rightMargin = rightMargin;
    addView(view, lp);//向DecorView中添加StatusBar或NavigationBar
    ......
    }
    </pre>
    后面接着的updateStatusGuard和updateNavigationGuard方法作用还在研究。

    StatusBar流程:
    zygote-SystemServer.main-SystemServer.run-SystemServer.startOtherServices-ActivityManagerService.systemReady-SystemServer.startSystemUi-systemUIService.onCreate-SystemUIApplication.startServicesIfNeeded-SystemBars.start-ServiceMonitor.start-SystemBars.onNoService-SystemBars.createStatusBarFromConfig(R.string.config_statusBarComponent表示PhoneStatusBar)-PhoneStatusBar.start-BaseSatusBar.start-PhoneStatusBar.createAndAddWindows-PhoneStatusBar.addStatusBarWindow-PhoneStatusBar.makeStatusBarView
    其中makeStatusBarView实例化StatusBarWindow,也就是真实显示statusbar各种图标的布局,然后在addStatusBarWindow中进行添加操作:
    <pre>
    private void addStatusBarWindow() {
    makeStatusBarView();
    mStatusBarWindowManager = new StatusBarWindowManager(mContext);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());//mStatusBarWindow是已经实例化的statsbar布局

    </pre>
    最后来看StatusBarWindowManager的add方法:
    <pre>
    public void add(View statusBarView, int barHeight) {
    ......
    mWindowmanager.addView(mStatusBarView, mLp);
    ......
    }
    </pre>
    很明显,这里向window添加了mStatusBarView布局,也就是状态栏布局。

    相关文章

      网友评论

          本文标题:WindowInsets和StatusBar

          本文链接:https://www.haomeiwen.com/subject/zalamttx.html