如何为animateIntAsState自定义缓动,让数值末尾段动画变慢
解决方案
方案1:自定义分段缓动Easing
Compose的Easing是单方法接口,输入为动画的时间进度(01)**,输出为**数值映射进度(01),我们可以通过分段映射实现需求:
- 时间进度走到预设阈值(比如80%)时,数值进度直接走到拐点位置(比如0.9867,对应296/300的数值比例)
- 剩余20%的时间,数值进度从0.9867线性增长到1,实现末尾慢速效果
通用自定义Easing实现代码:
// 自定义分段缓动 class SegmentEasing( // 拐点时间占总时长的比例,0.8代表前80%时间走前面的快速段 private val timeFractionAtInflection: Float = 0.8f, // 拐点对应的数值占总区间的比例,示例为296/300≈0.9867f private val valueFractionAtInflection: Float = 296f/300f ) : Easing { override fun transform(fraction: Float): Float { return if (fraction < timeFractionAtInflection) { // 前timeFractionAtInflection比例的时间,快速走到valueFractionAtInflection的数值进度 (fraction / timeFractionAtInflection) * valueFractionAtInflection } else { // 剩余时间,慢速从valueFractionAtInflection走到1 val remainingTimeFraction = (fraction - timeFractionAtInflection) / (1f - timeFractionAtInflection) valueFractionAtInflection + remainingTimeFraction * (1f - valueFractionAtInflection) } } }
使用示例:
val targetValue by remember { mutableStateOf(300) } val animatedValue by animateIntAsState( targetValue = targetValue, animationSpec = tween( durationMillis = 1500, // 总动画时长可自行调整 easing = SegmentEasing( timeFractionAtInflection = 0.8f, valueFractionAtInflection = 296f/300f ) ) ) // 直接使用animatedValue渲染即可
方案2:使用Keyframes关键帧动画实现(无需自定义Easing)
如果不想单独封装Easing,也可以直接用keyframes动画规格,直接指定不同时间点的数值:
val animatedValue by animateIntAsState( targetValue = 300, animationSpec = keyframes { durationMillis = 1500 // 1200ms(总时长的80%)的时候走到296,前面用快的缓动 296 at 1200 with FastOutSlowInEasing // 剩余300ms从296走到300,用线性缓动数值变化更均匀 300 at 1500 with LinearEasing } )
你可以根据实际观测效果调整总时长、拐点时间/数值比例,来达到最符合预期的末尾慢速效果。
内容的提问来源于stack exchange,提问作者Barrufet
相关产品推荐
相关产品推荐

