Jetpack compose animateFloat 不更新动画速度

问题描述 投票:0回答:1

我试图在每次页面刷新时增加动画速度,但它没有按预期工作。下面是我的代码:

@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


}

我添加的

Log
显示动画速度每次都在更新,但图像上的旋转速度根本没有改变。

有人可以帮我理解为什么吗?

kotlin android-jetpack-compose android-animation android-jetpack-compose-material3 jetpack-compose-animation
1个回答
0
投票

发生这种情况的原因是 TransitionAnimationState 创建一次,并且不会根据源代码中的任何其他参数更改。

@Composable public fun <T, V : AnimationVector> InfiniteTransition.animateValue( initialValue: T, targetValue: T, typeConverter: TwoWayConverter<T, V>, animationSpec: InfiniteRepeatableSpec<T>, label: String = "ValueAnimation" ): State<T> { val transitionAnimation = remember { TransitionAnimationState(initialValue, targetValue, typeConverter, animationSpec, label) } // Rest of the code }
取而代之的是,您可以使用 Animatable,每次在循环中更改 

animationSpec

 中的动画持续时间以创建无限过渡时,您都可以使用它来制作不同的 
LaunchedEffect
 动画。

您传递给补间的不是动画速度而是动画持续时间。如果你想让它旋转得更快,你需要减小该值。

但是对于Animatable来说重要的是

当动画被中断时,它会从当前值开始到目标并具有相同的缓动,这意味着如果从0度到360度需要1秒,而当你在300度中断时它会再次出现需要 1 秒才能达到 360,这使得中断后的动画速度变慢。因此,您可以根据 360 度的接近程度调整第一个动画持续时间

@Preview @Composable fun ScreenReport() { var isRefreshing by remember { mutableStateOf(false) } val ptrState = rememberPullToRefreshState() var animationDuration by remember { mutableIntStateOf(2000) } val animatable = remember { Animatable(0f) } LaunchedEffect(animationDuration) { while (isActive) { try { animatable.animateTo(targetValue = 360f, animationSpec = tween(animationDuration, easing = LinearEasing)) if (animatable.value >= 360f) { animatable.snapTo(targetValue = 0f) } } catch (exception: CancellationException) { val currentValue = animatable.value // This makes sure that animation after interruption runs at same duration with newly assigned duration animatable.animateTo( targetValue = 360f, tween((animationDuration * currentValue / 360).toInt(), easing = LinearEasing) ) } } } Box( modifier = Modifier .fillMaxSize() .padding(bottom = 8.dp, top = 16.dp) .background(MaterialTheme.colorScheme.background), contentAlignment = Alignment.Center ) { PullToRefreshBox( modifier = Modifier .fillMaxSize() .padding(8.dp), state = ptrState, isRefreshing = isRefreshing, onRefresh = { isRefreshing = true animationDuration += 2000 isRefreshing = false }, ) { Column( modifier = Modifier .align(Alignment.TopCenter) .verticalScroll(rememberScrollState()) ) { Icon( imageVector = Icons.Filled.Star, modifier = Modifier .align(Alignment.CenterHorizontally) .size(100.dp) .graphicsLayer { rotationZ = animatable.value }, contentDescription = null ) Text( "angle: ${animatable.value.toInt()}\n" + "animationDuration: $animationDuration" ) } } } }
    
© www.soinside.com 2019 - 2024. All rights reserved.