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>
参考: