当前位置:   article > 正文

WindowInsets和StatusBar_android.view.windowinsets.type.status_bars

android.view.windowinsets.type.status_bars

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方法

@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;
}

开头就直接调用了View的dispatchApplyWindowInsets处理insets,然后直接判断是否消费,如果没有消费就依次分发给child,直到有child消费insets就退出,下面先看View的dispatchApplyWindowInsets:

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;
      }

如果向View注册了OnApplyWindowInsetsListener监听器,就直接用监听器截取Insets操作返回,否则执行onApplyWindowInsets方法,因为DecorView没有注册监听器但重写了onApplyWindowInsets方法,所以执行DecorView的onApplyWindowInsets:

@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
    ...
    insets = updateColorViews(insets, true/animate/);
    insets = updateStatusGuard(insets);
    updateNavigationGuard(insets);
    ...
    return insets
}

在updateColorViews方法中,执行了两次updateColorViewInt方法,第一次传入的参数是mNavigationColorViewState,第二次传入mStatusColorViewState,代码如下:

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);
}

结合上面传入参数的名字,能够看出这段代码就是向DecorView中添加窗口顶部的StatusBar状态栏(显示电量、手机信号)的占位View和底部NavigationBar导航栏(三个大按钮的虚拟栏)的占位View,因为他们只是添加一个设置了背景色的View,所以只是占位用。代码如下:

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
    ......
}

后面接着的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中进行添加操作:

 private void addStatusBarWindow() {
    makeStatusBarView();
    mStatusBarWindowManager = new StatusBarWindowManager(mContext);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());//mStatusBarWindow是已经实例化的statsbar布局
}

最后来看StatusBarWindowManager的add方法:

public void add(View statusBarView, int barHeight) {
    ......
    mWindowmanager.addView(mStatusBarView, mLp);
    ......
}

很明显,这里向window添加了mStatusBarView布局,也就是状态栏布局。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/251020
推荐阅读
相关标签
  

闽ICP备14008679号