沉浸式探索

        目前市场上的好多应用都已经使用了沉浸式,实现方式可以有多中,其中在主题中可以设置两个属性:

 
//这两个属性默认都是false,
//windowTranslucentStatus指的是状态栏是半透明,
//当这个值为false时,可以设置statusBarColor的颜色,
//当为true时,statusBarColor不起作用,内容会处于状态栏(半透明)的下面
<item name="android:windowTranslucentStatus">true</item>
//windowTranslucentNavigation指的是导航栏的半透明
//当这个值为false时,可以设置navigationBarColor的颜色
//当这个值为true时,navigationBarColor不起作用,内容会处于导航栏(半透明)和状态栏下面
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">#ff0000</item>
<item name="android:navigationBarColor">#ff0000</item>


当需要把状态栏的半透明换成和底背景一样时,只需要把windowtranslucentStatus改成false或是去掉即可,这两个属性是在PhoneWindow中获取并设置的,让我们来看一下generateLayout(DecorView decor)(这个方法是在setContentView()中被调用到的)这个方法是如何设置的:

if (a.getBoolean(R.styleable.Window_windowTranslucentStatus,
        false)) {
    setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS
            & (~getForcedWindowFlags()));
}

if (a.getBoolean(R.styleable.Window_windowTranslucentNavigation,
        false)) {
    setFlags(FLAG_TRANSLUCENT_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION
            & (~getForcedWindowFlags()));
}
其实就是调用了Window的setFlags()方法,还有上面设置的颜色也是在这里获取的

if (!mForcedStatusBarColor) {
    mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
}
if (!mForcedNavigationBarColor) {
    mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
}

这里获取到颜色后会在DecorView中进行设置,

private int calculateStatusBarColor() {
    return calculateStatusBarColor(mWindow.getAttributes().flags,
            mSemiTransparentStatusBarColor, mWindow.mStatusBarColor);
}

public static int calculateStatusBarColor(int flags, int semiTransparentStatusBarColor,
        int statusBarColor) {
    return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? semiTransparentStatusBarColor
            : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? statusBarColor
            : Color.BLACK;
}

这里就是决定statusBarColor的颜色到底是哪一个。

        对于这里的所有设置都可以在代码中进行设置,具体的可以查看郭霖的这一篇点击打开链接

        不管是在代码中设置还是在主题中设置,最后决定权还是在DecorView这里,

WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
    WindowManager.LayoutParams attrs = mWindow.getAttributes();
    //主题中设置的系统UI属性在这里可以获取 attrs.systemUiVisibility
    //代码中设置的系统UI属性在这里可以获取 getWindowSystemUiVisibility()
    int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
    
    ...
    
    // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
    // to ensure that the rest of the view hierarchy doesn't notice it, unless they've
    // explicitly asked for it.
    boolean consumingNavBar = (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
                    && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
                    && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
                    || mLastShouldAlwaysConsumeNavBar;

    // If we didn't request fullscreen layout, but we still got it because of the
    // mForceWindowDrawsStatusBarBackground flag, also consume top inset.
    boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
            && (sysUiVisibility & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
            && (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
            && (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
            && mForceWindowDrawsStatusBarBackground
            && mLastTopInset != 0;

    int consumedTop = consumingStatusBar ? mLastTopInset : 0;
    int consumedRight = consumingNavBar ? mLastRightInset : 0;
    int consumedBottom = consumingNavBar ? mLastBottomInset : 0;
    int consumedLeft = consumingNavBar ? mLastLeftInset : 0;

    if (mContentRoot != null
            && mContentRoot.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mContentRoot.getLayoutParams();
        if (lp.topMargin != consumedTop || lp.rightMargin != consumedRight
                || lp.bottomMargin != consumedBottom || lp.leftMargin != consumedLeft) {
            lp.topMargin = consumedTop;
            lp.rightMargin = consumedRight;
            lp.bottomMargin = consumedBottom;
            lp.leftMargin = consumedLeft;
            mContentRoot.setLayoutParams(lp);

            if (insets == null) {
                // The insets have changed, but we're not currently in the process
                // of dispatching them.
                requestApplyInsets();
            }
        }
        if (insets != null) {
            insets = insets.replaceSystemWindowInsets(
                    insets.getSystemWindowInsetLeft() - consumedLeft,
                    insets.getSystemWindowInsetTop() - consumedTop,
                    insets.getSystemWindowInsetRight() - consumedRight,
                    insets.getSystemWindowInsetBottom() - consumedBottom);
        }
    }

    if (insets != null) {
        insets = insets.consumeStableInsets();
    }
    return insets;
}
从这里可以看出,沉浸式其实就是根据设置的属性计算内容所占的空间大小。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值