布局含FragmentContainerView时Bottom Sheet Fragment不显示排查
问题根因拆解
你碰到的是FragmentContainerView与CoordinatorLayout、BottomSheet协同的典型层级冲突,没有复杂的业务代码问题,本质是布局机制的时序和逻辑错位:
- Z轴绘制层级的时序错位
按你写的布局顺序,本来应该是先绘制底层的NavHost内容,再浮绘上层的BottomSheet所有内容。但FragmentContainerView在运行时完成NavHostFragment附加的过程中,为了支持Fragment转场动画,会主动把自身的Z轴层级抬到同级视图的最顶端——这个抬升动作发生在BottomSheetBehavior完成自身层级初始化之后,根本触发不了BottomSheet的层级重排逻辑。
最终的实际绘制顺序变成了:底层是BottomSheet的静态布局(ConstraintLayout、TabLayout、ViewPager),最上层是被抬升的NavHostFragmentContainerView,直接覆盖了ViewPager所在的区域。
之所以折叠状态、甚至展开后Tab栏都能正常显示,是因为NavHost本身设置了android:layout_marginBottom="?android:attr/actionBarSize":折叠状态下两者的显示区域刚好错开;展开后Tab栏随BottomSheet上移,刚好落在NavHost透明的区域边界上,所以没有被遮挡,但ViewPager的承载区域完全落在NavHost的不透明覆盖范围内,视觉上就是内容完全空白。 - 视图测量流程的打断冲突
FragmentContainerView在运行时附加NavHostFragment时,会强制将自身的测量边界重置为整个CoordinatorLayout的完整可用区域,抵消原本设置的marginBottom效果。这个过程会打断CoordinatorLayout的整体测量流程,原本BottomSheet内ViewPager的视图没有拿到正确的尺寸测量结果,ViewPager为了适配测量异常的父容器,会把内部加载的Fragment视图尺寸设为0,进一步放大了空白的表现。
你测试时把FragmentContainerView换成旧版<fragment>标签就正常,是因为旧标签是在布局inflate的同步阶段就完成了Fragment附加,整个测量流程和层级顺序是静态固定的,不会触发上述的运行时层级抬升和测量打断问题,BottomSheet的所有内容自然能正常展示。
可落地的修复方向
- 直接从
FragmentContainerView上移除app:layout_behavior="@string/appbar_scrolling_view_behavior",这个Behavior本来是配合AppBarLayout做偏移的,放在NavHost上会在BottomSheet滑动时错误调整自身位置和层级。 - 给BottomSheet的根布局(绑定了
BottomSheetBehavior的ConstraintLayout)设置更高的固定elevation值(比如16dp),强制把BottomSheet的Z轴层级固定在NavHost之上,避免被动态抬升的FragmentContainerView遮挡。 - 给
ViewPager设置明确的固定高度值,不要完全依赖父布局的约束测量,避免测量流程被打断后出现尺寸为0的问题。
内容的提问来源于stack exchange,提问作者Zero
相关产品推荐
相关产品推荐

