如何在Dialog Fragment中实现Fragment间的翻转动画切换?
实现DialogFragment之间的翻转动画切换
嘿,这个问题我之前折腾过!其实DialogFragment的卡片翻转动画和普通Fragment的核心逻辑是相通的,但因为DialogFragment是依附于系统窗口的,所以得调整几个关键细节才能让动画正常工作,我给你一步步捋清楚:
第一步:准备翻转动画资源
和官网的普通Fragment动画逻辑一致,我们需要在res/animator目录下创建四个动画文件,分别对应翻入、翻出的正向和反向效果:
card_flip_right_in.xml(从右侧翻入)
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:valueFrom="1.0" android:valueTo="0.0" android:propertyName="alpha" android:duration="0" /> <objectAnimator android:valueFrom="-180" android:valueTo="0" android:propertyName="rotationY" android:interpolator="@android:interpolator/accelerate_decelerate" android:duration="@integer/card_flip_time_full" /> <objectAnimator android:valueFrom="0.0" android:valueTo="1.0" android:propertyName="alpha" android:startOffset="@integer/card_flip_time_half" android:duration="1" /> </set>
card_flip_right_out.xml(向右侧翻出)
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:valueFrom="0" android:valueTo="180" android:propertyName="rotationY" android:interpolator="@android:interpolator/accelerate_decelerate" android:duration="@integer/card_flip_time_full" /> <objectAnimator android:valueFrom="1.0" android:valueTo="0.0" android:propertyName="alpha" android:startOffset="@integer/card_flip_time_half" android:duration="1" /> </set>
card_flip_left_in.xml(从左侧翻入,返回时的反向动画)
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:valueFrom="1.0" android:valueTo="0.0" android:propertyName="alpha" android:duration="0" /> <objectAnimator android:valueFrom="180" android:valueTo="0" android:propertyName="rotationY" android:interpolator="@android:interpolator/accelerate_decelerate" android:duration="@integer/card_flip_time_full" /> <objectAnimator android:valueFrom="0.0" android:valueTo="1.0" android:propertyName="alpha" android:startOffset="@integer/card_flip_time_half" android:duration="1" /> </set>
card_flip_left_out.xml(向左侧翻出,返回时的反向动画)
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:valueFrom="0" android:valueTo="-180" android:propertyName="rotationY" android:interpolator="@android:interpolator/accelerate_decelerate" android:duration="@integer/card_flip_time_full" /> <objectAnimator android:valueFrom="1.0" android:valueTo="0.0" android:propertyName="alpha" android:startOffset="@integer/card_flip_time_half" android:duration="1" /> </set>
然后在res/values/integers.xml里定义动画时长:
<integer name="card_flip_time_full">500</integer> <integer name="card_flip_time_half">250</integer>
第二步:配置DialogFragment的窗口样式
这是最关键的一步!默认的DialogFragment自带窗口背景和边框,翻转动画会显得非常突兀,所以我们要把它改成全屏、透明背景的样式:
以第一个DialogFragment为例:
class FirstDialogFragment : DialogFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 设置全屏无框样式 setStyle(STYLE_NO_FRAME, android.R.style.Theme_Black_NoTitleBar_Fullscreen) } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val dialog = super.onCreateDialog(savedInstanceState) dialog.window?.apply { // 设置窗口背景为透明 setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) // 去掉默认标题栏 requestFeature(Window.FEATURE_NO_TITLE) } return dialog } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // 加载你的自定义布局 return inflater.inflate(R.layout.fragment_first_dialog, container, false) } }
第二个DialogFragment需要完全复制这个配置,确保两者的窗口样式完全一致。
第三步:实现DialogFragment的切换逻辑
现在我们可以像切换普通Fragment一样,用FragmentTransaction来切换两个DialogFragment,同时绑定自定义动画:
比如在FirstDialogFragment的按钮点击事件里:
view.findViewById<Button>(R.id.btn_switch).setOnClickListener { val secondDialog = SecondDialogFragment() parentFragmentManager.beginTransaction() // 设置进出动画和返回时的反向动画 .setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out ) // 替换容器中的Fragment(这里的R.id.fragment_container是Activity中用来承载Dialog的FrameLayout) .replace(R.id.fragment_container, secondDialog) // 添加到回退栈,支持返回键回到上一个Dialog .addToBackStack(null) .commit() }
几个重要注意事项
- 必须设置全屏透明:如果跳过这一步,翻转动画时会看到黑色的窗口背景,完全破坏视觉效果。
- 用FragmentTransaction切换:不要用
dismiss()+show()的组合,这种方式无法直接应用自定义切换动画,replace+addToBackStack能完美适配动画逻辑。 - 布局要充满屏幕:你的DialogFragment布局要设置宽高为
match_parent,确保动画覆盖整个屏幕,和普通Fragment的效果一致。
这样操作之后,你的两个DialogFragment就能实现和官网普通Fragment完全一致的翻转动画切换效果啦!
内容的提问来源于stack exchange,提问作者Yadu Mohan
相关产品推荐
相关产品推荐

