显示Dialog时如何为原有Fragment添加配套的退出过渡动画
全屏Dialog触发底层Fragment同步退场动画解决方案
根因说明
DialogFragment本质是在当前Activity的Window上新增独立Dialog层,默认show()方法仅执行添加DialogFragment的单个事务,底层宿主Fragment未被执行隐藏/移除操作,因此不会触发FragmentTransaction配置的退场动画,仅Dialog自身的入场动画会生效。
可行解决方案
方案1:手动同步执行底层Fragment退场动画
无需改动原有Dialog逻辑,在Dialog展示前主动触发底层Fragment的退场动画,和Dialog入场动画保持时长一致即可:
- 定义Dialog入场动画和底层Fragment退场动画,确保两者时长相同
- 展示Dialog前执行底层Fragment的退场动画
- 在Dialog的dismiss回调中执行底层Fragment的还原入场动画
示例代码:
// 配置Dialog入场动画,时长设为300ms fullScreenDialog.dialog?.window?.setWindowAnimations(R.style.FullScreenDialogEnterAnim) // 拿到当前可见的底层Fragment,执行右滑退场动画,和Dialog入场时长一致 supportFragmentManager.findFragmentById(R.id.fragment_container)?.view?.apply { animate() .translationX(resources.displayMetrics.widthPixels.toFloat()) .setDuration(300) .withEndAction { // 动画结束后再展示Dialog,也可以同步启动看需求 fullScreenDialog.show(supportFragmentManager, "FullDialogTag") } .start() } // Dialog关闭时还原底层Fragment位置 fullScreenDialog.setOnDismissListener { supportFragmentManager.findFragmentById(R.id.fragment_container)?.view?.animate() .translationX(0f) .setDuration(300) .start() }
方案2:将全屏Dialog改为普通Fragment加载
如果不需要Dialog的窗口特性,直接把全屏Dialog页面改造为普通Fragment,用标准FragmentTransaction加载,原有配置的页面跳转动画直接生效:
val transaction = supportFragmentManager.beginTransaction() // 沿用原有页面跳转的动画配置 transaction.setCustomAnimations( R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right ) transaction.replace(R.id.fragment_container, fullScreenPageFragment) transaction.addToBackStack(null) transaction.commit()
该方案无需额外适配动画,还可复用原有页面跳转的逻辑,仅需要自行实现返回键关闭、事件拦截等原Dialog自带的逻辑即可。
方案3:自定义DialogFragment事务,同步隐藏底层Fragment
重写DialogFragment的show逻辑,手动构造FragmentTransaction,在添加DialogFragment的同时隐藏底层Fragment,让事务动画同时作用于两个Fragment:
val transaction = supportFragmentManager.beginTransaction() transaction.setCustomAnimations( R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right ) // 隐藏当前底层Fragment,触发其退场动画 transaction.hide(currentVisibleFragment) // 添加DialogFragment,触发其入场动画 transaction.add(R.id.fragment_container, fullScreenDialog, "FullDialogTag") transaction.addToBackStack(null) transaction.commit()
使用该方案需要注意将DialogFragment的Window配置为全屏匹配父容器,避免显示异常,同时处理好onHiddenChanged的业务逻辑。
注意事项
- 所有关联动画的时长必须严格保持一致,避免出现动画不同步的割裂感
- 手动设置View动画时需要在Fragment销毁时取消未完成的动画,避免内存泄漏
- 如果使用Navigation组件,可直接给Dialog目的地和当前页面目的地配置对应进出动画,导航组件会自动同步执行
内容的提问来源于stack exchange,提问作者Comfy Cat
相关产品推荐
相关产品推荐

