如何在Jetpack Compose中为LinearProgressIndicator添加动画效果?

12

我有一个 LinearProgressIndicator ,它可以正确地显示当前进度。现在我想要进度条能够动画显示,并且我认为使用 animateFloatAsState 应该非常简单。但是,不确定我哪里出错了,因为使用下面的代码,虽然显示位置正确,但进度条并没有动画效果。

@Composable
fun MyIndicator() {
    val progressAnimDuration = 1500
    val progressAnimation by animateFloatAsState(
        targetValue = 0.35f
        animationSpec = tween(durationMillis = progressAnimDuration, easing = FastOutSlowInEasing)
    )
     LinearProgressIndicator(
        progress = progressAnimation,
        ...
        modifier = Modifier           
           .fillMaxWidth()
           .clip(RoundedCornerShape(20.dp)). // Rounded edges
    )
}

无论何时我在屏幕上展示该组件时,我都希望进度条动画能够正确呈现。但实际情况是进度条不会进行动画,而是直接显示在正确的进度状态。
这里出了什么问题? :)
6个回答

19

我遇到了类似的问题,在我的情况下,我使用LaunchedEffect来更新进度从零到期望值

@Composable
fun MyIndicator(indicatorProgress: Float) {
   var progress by remember { mutableStateOf(0f) }
    val progressAnimDuration = 1500
    val progressAnimation by animateFloatAsState(
        targetValue = indicatorProgress, 
        animationSpec = tween(durationMillis = progressAnimDuration, easing = FastOutSlowInEasing)
    )
    LinearProgressIndicator(
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(20.dp)), // Rounded edges
        progress = progressAnimation
    )
    LaunchedEffect(indicatorProgress) {
        progress = indicatorProgress
    }
}

1
将此标记为正确答案,因为它更接近回答我的问题:一旦组件变为可见状态,立即开始动画。最终我最终采用了相同的方法(请参见下面的评论)。 - Johan Paul
1
我在没有使用LaunchedEffectprogress变量的情况下实现了相同的结果。 - Douglas Fornaro
1
对我来说不起作用。它立即处于最终状态。不知道我错过了什么... - west44
对我也不起作用,只是立即显示最终状态。 - Unique Identifier
1
在progressAnimation的targetValue中,我使用了progress变量而不是indicatorProgress,现在它对我起作用了 :D - Carlosgub

1
这是我做的方法。我使用进度指示器来模拟加载效果,然后跳转到登录界面。
var currentProgress by remember { mutableFloatStateOf(0f) }
val context = LocalContext.current

// jump to Login Activity after animation
val currentPercentage by animateFloatAsState(
    targetValue = currentProgress,
    animationSpec =  tween( durationMillis = 1000, easing = LinearEasing),
    label = "progress",
    finishedListener = { _ -> context.startActivity(Intent(context, LoginActivity3::class.java)) }
)

LaunchedEffect(key1 = Unit){
    currentProgress = 1f
}

Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center)
{
    Column(horizontalAlignment = Alignment.CenterHorizontally)
    {
        LinearProgressIndicator(
            modifier = Modifier.width(220.dp).height(5.dp),
            progress = currentPercentage,
            color = colorResource(R.color.green_500)
        )
    }
}

0
我在 animateFloatAsState 中发现了一个非常重要的参数 visibilityThreshold,你必须将其设置为 0.001f 才能使其正常工作。

0

在我的案例中,它已经运作。

 var animationPlayed by remember {
            mutableStateOf(false)
        }
        val currentPercentage = animateFloatAsState(targetValue =
            if(animationPlayed) percentage else 0f,
            animationSpec = tween( durationMillis = 4000)
        )
        LaunchedEffect(key1 = true){
            animationPlayed=true
        }
    
    LinearProgressIndicator(...progress = currentPercentage)

0
你可以使用Animatable,但你需要LaunchEffect来触发动画。
  val percent = remember { Animatable(0f) }


  LaunchedEffect(key1 = Unit, block = {
        percent.animateTo(
            targetValue = yourPercentage ,
            animationSpec = tween(
                durationMillis = (1000 * (1f - percent.value)).toInt(),
                easing = FastOutLinearInEasing
            )
        )
    })

     LinearProgressIndicator(
            progress = percent.value
        )

0
我通过在0处设置一个可变状态来解决了这个问题,然后在代码结束时将其设置为null以触发重新组合。
{
var starterProgressValue by remember { mutableStateOf<Float?>(0f) }
val actualProgress = 1f

AnimatedProgressBar(
    progress = starterProgressValue ?: actualProgress,
    duration = 3000,
    modifier = Modifier
        .align(Alignment.CenterStart)
        .height(12.dp)
        .fillMaxWidth()
)

starterProgressValue = null

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接