美文网首页android高级android
从fitSystemWindows说起

从fitSystemWindows说起

作者: Simon_z | 来源:发表于2016-10-01 17:00 被阅读1657次

从fitSystemWindows说起

原先做状态栏颜色修改, 或者图片显示在状态栏之下, 一直都是copy代码, 没有具体去看, 最近有时间研究了下,涉及到的东西还是挺多的, 慢慢看,慢慢填坑

首先 fitSystemWindows 到底是有啥作用

首先看个链接,查找资料的时候,同样看见有个人对此的困惑了, 在stackoverflow上提了个问题;
fitSystemWindows我个人的理解是,view有这个标志位之后,view会自动调整去适应系统UI,通俗的说,就是这个设置为true后, 在view在绘制时,会调整自身,为系统的状态栏,导航栏等空出位置, 让状态栏等不会盖住我们的布局;

这个标志,在4.4之前没怎么用过,基本没啥问题, 而在4.4后, 出现了沉浸试状态栏, 状态栏颜色, 后来又配合MD实现, 将View#fitSystemWindows() 扩展成 View#dispatchApplyWindowInsets() 和 View#onApplyWindowInsets()方法, 然后这个就变的复杂了 - -

fitSystemWindows有啥用,怎么用,有个Android的攻城师写了片文章的 https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec?linkId=19685562#.3a5ertaa7 ;国内已经有翻译了, 不过还是建议自己看原文, 我下面也主要是对这偏文章,结合我自己的理解和试验所写;

使用fitSystemWindows, 你要知道这几点

  • 它是用来告诉view, 为系统UI提供空间的, 免得让系统UI覆盖在我们的布局上了
  • fitSystemWindows按照深度优先的方式生效
    各个拥有这个标志位的view,在被调用这个方法的时候是有顺序的(这功能感觉在5.0之后才凸显出作用,5.0添加了View#dispatchApplyWindowInsets()方法, 可以将WindowInsets分发下去, 让其他的view可以处理; 在之前,系统的view都是第一个被调用的view将它给消耗了,处理方式也简单粗暴,直接修改自身的padding留出空间, 后面的都不会有机会处理这个; 后面出的兼容包可以自己出处理这个问题);
  • Insets是相对与全屏幕来说的
    Insets可能在Layout之前就要应用的,
  • View所有的padding都没被覆盖掉
    设置fitSystemWindows=true之后, 设置在这个view上的padding都会失效

如果想让RecycleView的内容滚动到状态栏之下, 可以同时设置android:fitsSystemWindows="true"android:clipToPadding="false", 这样在布局初始化的时候,内容不会在状态栏之下, 滚动的时候, 内容可以滚到状态栏之下;

android:clipToPadding="false"的作用是是让padding的位置也可以用来绘制, clipToPadding默认是true

自定义fitsSystemWindows

在4.4之下, 在在定义的view中重写fitSystemWindows()方法去实现自己的功能, 返回true, 代表你消耗了Insets, 否则返回false,让其他的view有机会去处理;

5.0后,废弃了'fitSystemWindows()'方法,用了2个新方法来扩展和简化流程;重写onApplyWindowInsets()方法,这个方法允许你只消耗部分Insets, 然后可以调用dispatchApplyWindowInsets() 让该View的子view去接着处理Insets;

另外,如果只在5.0之上使用,并不需要继承View,跟好的方法是使用ViewCompat.setOnApplyWindowInsetsListener(),在ViewCompat中也提供onApplyWindowInsets()dispatchApplyWindowInsets(),这样可以免除写兼容代码的麻烦

read the fucking source code

先看4.4的代码

//View#fitSystemWindows
protected boolean fitSystemWindows(Rect insets) {
    if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        Rect localInsets = sThreadLocal.get();
        if (localInsets == null) {
            localInsets = new Rect();
            sThreadLocal.set(localInsets);
        }
        // conputeFitSystemWindow方法中, 只要有 FITS_SYSTEM_WINDOWS标志, 就会返回true
        boolean res = computeFitSystemWindows(insets, localInsets);
        // 简单粗暴, 直接设置padding
        internalSetPadding(localInsets.left, localInsets.top,
                localInsets.right, localInsets.bottom);
        return res;
    }
    return false;
}

//在看下ViewGroup的#fitSystemWindows
@Override
protected boolean fitSystemWindows(Rect insets) {
    // 直接调用View的fitSystemWindows, 而在View中,只要有标志位,就会返回true
    boolean done = super.fitSystemWindows(insets);
    // 如果没消耗, 就给子view去处理
    if (!done) {
        final int count = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < count; i++) {
            done = children[i].fitSystemWindows(insets);
            if (done) {
                break;
            }
        }
    }
    return done;
}

代码上看,4.4的代码处理方式很简单, 由于绝大部分View都没重写这个方法, 基本上是第一个有fitSystemWindows=true的view, 就把Insets给消耗了; 处理方式也很粗暴, 直接添加padding;

CoordinatorLayout中, 会通过dispatchApplyWindowInsetsToBehaviors方法, 把Insets交给各个behave去处理

相关文章

  • 从fitSystemWindows说起

    从fitSystemWindows说起 原先做状态栏颜色修改, 或者图片显示在状态栏之下, 一直都是copy代码,...

  • fitSystemWindows

    从fitSystemWindows说起 原先做状态栏颜色修改, 或者图片显示在状态栏之下, 一直都是copy代码,...

  • FitSystemWindows

    在绘制View时,首先由根布局往下传WindowInsets,SystemBar的尺寸在WindowInsets ...

  • Android Toast文字不居中

    不要设置Activitytheme的fitSystemWindows 为true 或者使用getApplicati...

  • Android Toast文字不居中解决方案

    效果图 二种解决方案 不要设置Activitytheme的fitSystemWindows 为true toast...

  • View源码——fitSystemWindows详解

    基于api28 源码解析 该方法在窗口的insets发生变化时,被调用。View调用该方法,以调整内容来适应窗口的...

  • 从我写《说起》说起

    “知青”是当代国人既绕不开,又躲不过的一个沉重话题。不唯是涉及1700万人的上一辈和下一代如此庞大的群体,而是...

  • Android Toast文字不居中,文字超出背景

    二种解决方案1.不要设置Activity的theme的fitSystemWindows 为true 2.toast...

  • 从死亡说起

    庄子曾说:生也有涯,而知也无涯。 我们的生命是有限度的,而知识是没有限度的。 随着年龄的增大,我们会开始问自己这样...

  • 从别字说起

    现在网络上别字不少,隐约还变成一种时尚。我是不抵触的,因为那都是聊天啊微薄啊等环境,是娱乐化的,博得一笑而已。不过...

网友评论

  • 9ec5f2f617fb:答主我觉着最好能说明状态栏的下方是指“下方”和“下层”。有时候讲到内容区域会延伸到状态栏的下方,你说的下方是状态栏的下层呢还是布局当中的状态栏的下方?这样很容易让人困惑
  • 谷歌清洁工:两篇文文章都大量提到了Insets,如何去理解这个Insets是什么含义
    Simon_z:Insets 我感觉可以理解成一块区域, 系统的状态栏和App的Window重合的区域

本文标题:从fitSystemWindows说起

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