Fragment返回时触发Only TabItem instances can be added to TabLayout崩溃如何解决
崩溃触发原因
这个问题是Android Transition过渡动画框架和Material组件TabLayout的内部校验逻辑冲突导致的,具体触发链路如下:
- 从Fragment2返回Fragment1时,系统默认会执行Fragment的退场过渡动画,Transition框架的
Visibility过渡类会为即将消失的Fragment2内的View创建渲染快照,用于生成退场动画效果。 - 过渡动画的工具类
TransitionUtils.createViewBitmap在创建快照时,会临时把目标View(这里就是设置了动态visibility的TabLayout)添加到一个匿名临时父容器中完成测量渲染,生成快照后再将其从临时容器移除。 - 但TabLayout本身有强校验逻辑:它的
addViewInternal方法只允许添加TabItem类型的子View,任何其他类型的View被添加到TabLayout都会直接抛出你遇到的IllegalArgumentException。 - 你给TabLayout加上DataBinding的visibility动态绑定后,在Fragment退栈的生命周期节点,刚好会触发Transition框架对这个visibility可变的View的快照采集逻辑,而TabLayout本身又禁止非TabItem的View添加操作,两者冲突就会触发崩溃。因为动画执行和生命周期回调的时机存在时序差,所以崩溃是概率性出现的。
可选的其他修复方案
如果需要保留TabLayout的动态显示隐藏逻辑,可以选以下任意一种方案规避:
- 给Fragment2关闭退场/返回过渡动画,在Fragment2的
onCreate方法中添加如下代码:
setExitTransition(null); setReturnTransition(null);
- 调整布局结构,不要把TabLayout嵌套在ViewPager标签内部,改为平级布局,通过
setupWithViewPager方法绑定两者关联,原本的嵌套写法本身就不符合ViewPager的子View管理规范,也是触发问题的诱因之一。 - 把TabLayout的visibility控制改为代码手动设置,在Fragment退栈前提前将TabLayout设置为GONE,避开过渡动画的快照采集时机。
内容的提问来源于stack exchange,提问作者Rainmaker
相关产品推荐
相关产品推荐

