FragmentContainerView结合popUpTo的弹出动画层级异常问题
问题描述
布局与导航配置
主Activity使用FragmentContainerView承载导航组件:
<androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/main_nav_graph" />
现有三个Fragment(A、B、C),A→B、B→C均配置右侧滑入动画:
<action android:id="@+id/a_to_b" app:destination="@id/b" app:enterAnim="@anim/slide_in_right" app:exitAnim="@anim/nothing" app:popEnterAnim="@anim/nothing" app:popExitAnim="@anim/slide_out_right" />
Fragment C的「X」按钮点击后,配置直接返回Fragment A并伴随向下滑出动画:
<action android:id="@+id/cancel" app:destination="@id/a" app:enterAnim="@anim/nothing" app:exitAnim="@anim/slide_out_bottom" app:popEnterAnim="@anim/nothing" app:popExitAnim="@anim/nothing" app:popUpTo="@id/a" app:popUpToInclusive="true" />
动画文件
- Nothing动画(
res/anim/nothing.xml):
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300" android:fromYDelta="0%p" android:toYDelta="0%p" />
- 右侧滑入动画(
res/anim/slide_in_right.xml):
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300" android:fromXDelta="100%p" android:toXDelta="0" />
- 向下滑出动画(
res/anim/slide_out_bottom.xml):
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromYDelta="0%p" android:toYDelta="100%p" android:duration="300"/>
异常现象
除取消操作外,其余导航均正常。但点击C的「X」按钮时,Fragment A会直接覆盖在C之上,导致看不到C的向下滑出动画。预期弹出操作时,退出的Fragment(C)应绘制在进入的Fragment(A)之上,才能展示退出动画。
解决方案
核心原因
使用popUpTo并设置inclusive="true"时,导航组件会先将目标Fragment(A)加载到视图层级,再执行退出Fragment(C)的动画,导致A覆盖C。要让C的退出动画可见,需调整视图层级顺序,让C在动画期间保持在A上方。
具体实现
- 修改导航Action配置(推荐)
移除app:popUpToInclusive="true",调整后的Action配置:
<action android:id="@+id/cancel" app:destination="@id/a" app:enterAnim="@anim/nothing" app:exitAnim="@anim/slide_out_bottom" app:popEnterAnim="@anim/nothing" app:popExitAnim="@anim/nothing" app:popUpTo="@id/a" />
此配置会弹出B和C回到A,此时C作为退出的Fragment会在A上方执行动画,符合预期效果。
- 调整动画的Z轴层级
在slide_out_bottom.xml中添加android:zAdjustment="top",强制动画执行期间将视图置于顶层:
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromYDelta="0%p" android:toYDelta="100%p" android:duration="300" android:zAdjustment="top"/>
该属性会让执行动画的视图在动画期间临时提升Z轴层级,确保不会被新Fragment覆盖。
- 手动控制视图层级(备选)
在Fragment C的按钮点击事件中,先将C的视图置顶再执行导航:
// Fragment C中按钮点击逻辑 view?.bringToFront() findNavController().navigate(R.id.cancel)
内容的提问来源于stack exchange,提问作者sunilson
相关产品推荐
相关产品推荐

