如何使Jetpack Compose中的CircularProgressIndicator更流畅

huangapple go评论61阅读模式
英文:

How to make CircularProgressIndicator in jetpack compose smoother

问题

我正在构建一个显示分钟和秒的计时器,周围使用了一个CircularProgressIndicator来进行可视化。但是CircularProgressIndicator在更新时会从一秒钟跳到下一秒钟。有没有办法让它平稳流畅地运行?

我尝试了两个LaunchedEffect,一个用于计时器,一个用于CircularProgressIndicator,并尝试了一些疯狂的公式,但效果不太好。

以下是我目前的代码:

var currentTime by remember { mutableLongStateOf(totalTime) } // 例如,10
var progress by remember { mutableFloatStateOf(1f) }

// 动画
val progressAnimate by animateFloatAsState(
    targetValue = progress,
    animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
)

CircularProgressIndicator(
    progress = progressAnimate,
    modifier = Modifier.size(size = 300.dp),
    color = color,
    strokeWidth = 10.dp,
    strokeCap = StrokeCap.Round,
)

LaunchedEffect(isTimerRunning) {
    while (currentTime > 0) {
        delay(1000L)
        currentTime--
        progress = currentTime / totalTime.toFloat()
        onTimerChange(currentTime)
    }
}

希望这能帮助你解决问题。

英文:

I'm build a timer that shows the minutes and seconds, and around it a used a CircularProgressIndicator for the visuals. But the CircularProgressIndicator updates jumping from second to second. Is there a way to make it run smoothly, flowing?

I tried two LauchedEffect one for the timer and one for the CircularProgressIndicator and came up with some crazy formulas but it didn't sync up very well.

here is my code so far

var currentTime by remember { mutableLongStateOf(totalTime) } // 10 for example
var progress by remember { mutableFloatStateOf(1f) }

// animation
val progressAnimate by animateFloatAsState(
    targetValue = progress,
    animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
)

CircularProgressIndicator(
    progress = progressAnimate,
    modifier = Modifier.size(size = 300.dp),
    color = color,
    strokeWidth = 10.dp,
    strokeCap = StrokeCap.Round,
)

LaunchedEffect(isTimerRunning) {
    while (currentTime > 0) {
        delay(1000L)
        currentTime--
        progress = currentTime / totalTime.toFloat()
        onTimerChange(currentTime)
    }
}

答案1

得分: 0

我认为你正在寻找的是动画规范 tween,它的工作原理如下:

tween 会在指定的 durationMillis 内在起始值和结束值之间进行动画,使用缓动曲线。有关更多信息,请参阅缓动 (Easing)。
你还可以指定 delayMillis 来推迟动画的开始。

因此,你的代码应该是这样的:

var currentTime by remember { mutableLongStateOf(totalTime) } // 例如 10
var progress by remember { mutableFloatStateOf(1f) }

// 动画
val progressAnimate by animateFloatAsState(
    targetValue = progress,
    animationSpec = tween(
        durationMillis = 300, // 动画持续时间
        delayMillis = 50,    // 动画开始前的延迟
        easing = LinearOutSlowInEasing
    )
)

CircularProgressIndicator(
    progress = progressAnimate,
    modifier = Modifier.size(size = 300.dp),
    color = color,
    strokeWidth = 10.dp,
    strokeCap = StrokeCap.Round,
)

LaunchedEffect(isTimerRunning) {
    while (currentTime > 0) {
        delay(1000L)
        currentTime--
        progress = currentTime / totalTime.toFloat()
        onTimerChange(currentTime)
    }
}
英文:

I think what you are looking for is the animation spec tween and it works like this:

> tween animates between start and end values over the specified
> durationMillis using an easing curve. See Easing for more information.
> You can also specify delayMillis to postpone the start of the
> animation.

So your code would be:

    var currentTime by remember { mutableLongStateOf(totalTime) } // 10 for example
    var progress by remember { mutableFloatStateOf(1f) }
    
    // animation
    val progressAnimate by animateFloatAsState(
        targetValue = progress,
        animationSpec = tween(
            durationMillis = 300,//animation duration
            delayMillis = 50,//delay before animation start
            easing = LinearOutSlowInEasing
    )
    
    CircularProgressIndicator(
        progress = progressAnimate,
        modifier = Modifier.size(size = 300.dp),
        color = color,
        strokeWidth = 10.dp,
        strokeCap = StrokeCap.Round,
    )
    
    LaunchedEffect(isTimerRunning) {
        while (currentTime > 0) {
            delay(1000L)
            currentTime--
            progress = currentTime / totalTime.toFloat()
            onTimerChange(currentTime)
        }
    }

huangapple
  • 本文由 发表于 2023年6月15日 04:02:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76477164.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定