单activity多fragment切换时fitsSystemWindow无效

app的主界面使用一个activity+tabLayout+多个fragment来实现。
当需要每个fragment都实现透明状态栏时,需要在每个fragment的布局中添加fitsSystemWindows属性来避免内容部分覆盖在状态栏的位置。然而当添加了这个属性后却发现只有第一个fragment的布局起作用,其他无效。

先看一下当前布局结构:

<ConstraintLayout>
<TabLayout/>
<FrameLayout/>
</ConstraintLayout>

问题原因

在Activity生成时会消费WindowInsets使fitsSystemWindows属性生效,所以第一个fragment不会有问题。当切换fragment时,并不会重新消费fragment内的fitsSystemWindows属性,所以产生无效的情况。

解决

知道原因后就好办了,我们要在fragment显示的时候让WindowInsets重新消费。

方法

自定义FrameLayout来代替上面FrameLayout容器

public class WindowInsetsFrameLayout extends FrameLayout {

    public WindowInsetsFrameLayout(Context context) {
        this(context, null);
    }

    public WindowInsetsFrameLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public WindowInsetsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
            @Override
            public void onChildViewAdded(View parent, View child) {
                requestApplyInsets();
            }

            @Override
            public void onChildViewRemoved(View parent, View child) {

            }
        });
    }

    @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        int childCount = getChildCount();
        for (int index = 0; index < childCount; index++) {
            getChildAt(index).dispatchApplyWindowInsets(insets);
        }
        return insets;
    }
}

替换后的布局结构为:

<ConstraintLayout>
<TabLayout/>
<WindowInsetsFrameLayout/>
</ConstraintLayout>

参考:

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容