You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:18:09