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

如何在MotionLayout过渡期间平滑更改View的圆角半径?

解决MotionLayout过渡中修改Drawable圆角半径的问题

你提到的问题确实存在:MotionLayout的XML配置里,默认CustomAttribute仅支持颜色Drawable的切换,无法直接对ShapeDrawable的圆角半径做平滑过渡。以下是几种可行的解决方式:

方法一:监听过渡进度动态修改圆角

给MotionLayout添加过渡监听,在过渡过程中实时计算并更新目标View背景的圆角半径:

motionLayout.setTransitionListener(object : MotionLayout.TransitionListener {
    override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {}
    override fun onTransitionChange(motionLayout: MotionLayout?, startId: Int, endId: Int, progress: Float) {
        // 定义初始和目标圆角尺寸(需在dimens.xml中配置)
        val startRadius = resources.getDimension(R.dimen.start_corner_radius)
        val endRadius = resources.getDimension(R.dimen.end_corner_radius)
        // 根据过渡进度计算当前圆角值
        val currentRadius = startRadius + (endRadius - startRadius) * progress
        
        // 修改背景Drawable的圆角
        val bgDrawable = layout_player.background as GradientDrawable
        bgDrawable.cornerRadius = currentRadius
        layout_player.background = bgDrawable
    }
    override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {}
    override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}
})

注意:确保目标View的初始背景是GradientDrawable(XML中定义的shape默认就是这个类型),否则需要做类型兼容处理。

方法二:自定义可动画圆角的Drawable

通过自定义Drawable暴露圆角属性,让MotionLayout可以直接通过CustomAttribute过渡该属性:

  1. 自定义Drawable类:
class AnimatedCornerDrawable : GradientDrawable() {
    var cornerRadiusValue: Float
        get() = cornerRadius
        set(value) {
            cornerRadius = value
            invalidateSelf()
        }
}
  1. 在布局中设置该Drawable为目标View的背景:
<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/layout_player"
    android:background="@drawable/animated_corner_drawable"
    ...>
  1. 在MotionLayout的ConstraintSet中配置过渡属性:
<ConstraintSet android:id="@+id/start">
    <Constraint
        android:id="@+id/layout_player"
        ...>
        <CustomAttribute
            motion:attributeName="cornerRadiusValue"
            motion:customFloatValue="@dimen/start_corner_radius" />
    </Constraint>
</ConstraintSet>

<ConstraintSet android:id="@+id/end">
    <Constraint
        android:id="@+id/layout_player"
        ...>
        <CustomAttribute
            motion:attributeName="cornerRadiusValue"
            motion:customFloatValue="@dimen/end_corner_radius" />
    </Constraint>
</ConstraintSet>

这种方式可以实现完全平滑的圆角过渡,且无需额外的代码监听。

方法三:直接切换不同圆角的Drawable(无平滑过渡)

如果不需要平滑过渡,仅需在过渡前后切换背景Drawable,可使用customDrawableValue属性替代customColorDrawableValue:

<ConstraintSet android:id="@+id/start">
    <Constraint
        android:id="@+id/layout_player"
        ...>
        <CustomAttribute
            motion:attributeName="background"
            motion:customDrawableValue="@drawable/bg_player_control_part" />
    </Constraint>
</ConstraintSet>

<ConstraintSet android:id="@+id/end">
    <Constraint
        android:id="@+id/layout_player"
        ...>
        <CustomAttribute
            motion:attributeName="background"
            motion:customDrawableValue="@drawable/bg_player_control_part_round" />
    </Constraint>
</ConstraintSet>

此方式是直接替换Drawable,没有渐变效果,适合对过渡平滑度要求不高的场景。

内容的提问来源于stack exchange,提问作者Isuru Gunasekara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 13:30:40