先看布局
Fragment添加到FrameLayout中,当fragment切换时,只有第一个fragment的fitsSystemWindows起作用了
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.MainActivity">
<FrameLayout
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" />
<com.flyco.tablayout.CommonTabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:background="@color/bg_light"
android:elevation="3dp"
app:tl_iconHeight="@dimen/dp24"
app:tl_iconWidth="@dimen/dp24"
app:tl_indicator_height="0dp"
app:tl_textSelectColor="@color/main_color"
app:tl_textUnselectColor="@color/text3"
app:tl_textsize="0sp"
app:tl_underline_height="0dp">
</com.flyco.tablayout.CommonTabLayout>
</LinearLayout>
原因和解决方法
当第一个Fragment添加到Activity中的时候,Activity寻找出有fitsSystemWindows的子布局为其预留出状态栏的空间,其实就是设置一个padding,而其他Fragment添加到Activity中的时候,因为状态栏空间的适配已经被消费过一次了,Activity并不会再次去添加这个padding。因此我们需要自定义一个FrameLayout,重写它的状态栏空间适配的时机和它的适配事件的分发。因为Fragment是添加到FrameLayout这个容器的,给他设置一个布局层次结构改变的监听,当Fragment被添加进去的时候,通过requestApplyInsets()
方法使Activity重新进行一次状态栏空间的适配,因为FrameLayout中还有其他的Fragment,我们还需要重写onApplyWindowInsets()
方法,对其子View进行遍历,逐个分发状态栏空间的适配事件。
class WindowInsetsFrameLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
init {
//当层次结构发生改变时回调
setOnHierarchyChangeListener(object : OnHierarchyChangeListener {
override fun onChildViewAdded(parent: View, child: View) {
requestApplyInsets()
}
override fun onChildViewRemoved(parent: View, child: View) {
}
})
}
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
//对子View进行遍历,逐个分发状态栏空间的适配事件
for (index in 0 until childCount)
getChildAt(index).dispatchApplyWindowInsets(insets)
return insets
}
}
网友评论