Jetpack Compose中animateFloat动画速度无法更新的问题求助
问题:下拉刷新递增动画速度无效果,日志数值更新但图片旋转速度不变
尝试在每次页面下拉刷新时递增动画速度,但未达到预期效果。日志显示animationSpeed数值已更新,但图片的旋转速度完全没有变化。
代码示例
@Composable fun ScreenReport( ) { var isRefreshing by remember { mutableStateOf(false) } val ptrState = rememberPullToRefreshState() var animationSpeed by remember { mutableIntStateOf(1000) } val infiniteTransition = rememberInfiniteTransition(label = "") val angle by infiniteTransition.animateFloat( initialValue = 0F, targetValue = 360F, animationSpec = infiniteRepeatable( animation = tween(animationSpeed, easing = LinearEasing) ), label = "" ) Box( modifier = Modifier .fillMaxSize() .padding(bottom = 8.dp, top = 16.dp) .background(MaterialTheme.colorScheme.background) ) { PullToRefreshBox( modifier = Modifier.padding(8.dp), state = ptrState, isRefreshing = isRefreshing, onRefresh = { isRefreshing = true coroutineScope.launch { animationSpeed += 1000 isRefreshing = false } }, ) { Column( modifier = Modifier .align(Alignment.TopCenter) .verticalScroll(scrollState) ) { Log.i("TESTING", animationSpeed.toString()) MesIcon( painterResource = R.drawable.ic_cyclone, tint = MaterialTheme.colorScheme.secondary, modifier = Modifier .align(Alignment.CenterHorizontally) .graphicsLayer { rotationZ = angle } ) // More code here that's not relevant }
原因分析
rememberInfiniteTransition创建的无限动画是一次性绑定初始参数的:首次调用animateFloat时,animationSpec里的tween(animationSpeed)会使用当时animationSpeed的初始值(1000)创建动画。- 后续
animationSpeed的更新不会触发动画重新创建,因为infiniteTransition通过remember保留,不会因animationSpeed变化而重新初始化,旧动画会一直沿用最初的时长参数运行。
解决方法
给animateFloat添加key参数,将animationSpeed作为触发动画重建的标识。当animationSpeed变化时,key值改变,Compose会取消旧动画并创建使用新参数的新动画:
val angle by infiniteTransition.animateFloat( initialValue = 0F, targetValue = 360F, animationSpec = infiniteRepeatable( animation = tween(animationSpeed, easing = LinearEasing) ), label = "", key = animationSpeed // 新增key参数,关联animationSpeed )
另外注意:代码中coroutineScope需要用rememberCoroutineScope()获取,否则会报错,补充后完整的onRefresh部分应该是:
val coroutineScope = rememberCoroutineScope() // ... onRefresh = { isRefreshing = true coroutineScope.launch { animationSpeed += 1000 isRefreshing = false } },
内容的提问来源于stack exchange,提问作者Mervin Hemaraju
相关产品推荐
相关产品推荐

