Jetpack Compose 动画如何同时配置tween、spring等多个Animation Spec
Jetpack Compose 组合动画规格实现方案
Jetpack Compose 的动画规格支持通过+运算符按顺序拼接,不需要局限于单种规格配置,可直接实现「指定时长过渡+弹性效果」的需求,两种常用实现方案如下:
方案1:拼接tween与spring,保留真实物理弹性效果
spring()属于物理动画,本身无固定时长参数,动画时长由刚度、阻尼比、初始速度共同决定,可通过拼接tween控制主体过渡时长,剩余时间留给spring做回弹,总时长接近你需要的3000ms:
@Composable private fun TransitionAnimation() { var isAnimated by remember { mutableStateOf(false) } val transition = updateTransition(targetState = isAnimated, label = "") val rocketOffset by transition.animateOffset(transitionSpec = { if (this.targetState) { tween(1000) } else { // 前2700ms用tween完成主体移动,后接spring实现弹性回弹,总时长接近3000ms tween(durationMillis = 2700) + spring( dampingRatio = Spring.DampingRatioLowBouncy, stiffness = Spring.StiffnessLow ) } }, label = "rocket offset") { animated -> if (animated) Offset(200f, 0f) else Offset(200f, 500f) } Image( painter = painterResource(id = R.drawable.rocket), contentDescription = "Rocket", modifier = Modifier .size(100.dp) .offset(rocketOffset.x.dp, rocketOffset.y.dp) ) }
提示:如果需要调整总时长,可修改tween的durationMillis参数,或者调高spring的stiffness(刚度越高回弹越快,总时长越短)。
方案2:用keyframes实现严格固定时长的弹性效果
如果需要严格控制总时长为3000ms,可通过keyframes定义不同时间节点的位置,模拟弹性回弹效果,时长完全可控:
transitionSpec = { if (this.targetState) { tween(1000) } else { keyframes { durationMillis = 3000 // 前2700ms移动到超出终点50px的位置 Offset(200f, 550f) at 2700 with FastOutSlowInEasing // 2850ms回弹到低于终点20px的位置 Offset(200f, 480f) at 2850 // 3000ms回到终点位置 Offset(200f, 500f) at 3000 } } }
你可以根据自己想要的弹性幅度,调整各个时间节点的偏移数值和时间占比。
内容的提问来源于stack exchange,提问作者Ranjithkumar
相关产品推荐
相关产品推荐

