单activity多fragment切换时fitsSystemWindow无效

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

先看一下当前布局结构:




问题原因

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

替换后的布局结构为:




参考:

  • https://stackoverflow.com/questions/31190612/fitssystemwindows-effect-gone-for-fragments-added-via-fragmenttransaction
  • https://www.jianshu.com/p/cb92576f4e56

你可能感兴趣的:(单activity多fragment切换时fitsSystemWindow无效)