如何创建这样的弧形进度条动画
目前我已经用Canvas画了一个弧线,并使用animateFloatAsState API在进度条上添加了动画。但是第二张图片不是我所期望的。
[
](一个字母)
// e.g. oldScore = 100f newScore = 350f
// Suppose 250 points are into one level
@Composable
fun ArcProgressbar(
modifier: Modifier = Modifier,
oldScore: Float,
newScore: Float,
level: String,
startAngle: Float = 120f,
limitAngle: Float = 300f,
thickness: Dp = 8.dp
) {
var value by remember { mutableStateOf(oldScore) }
val sweepAngle = animateFloatAsState(
targetValue = (value / 250) * limitAngle, // convert the value to angle
animationSpec = tween(
durationMillis = 1000
)
)
LaunchedEffect(Unit) {
delay(1500)
value = newScore
}
Box(modifier = modifier.fillMaxWidth()) {
Canvas(
modifier = Modifier
.fillMaxWidth(0.45f)
.padding(10.dp)
.aspectRatio(1f)
.align(Alignment.Center),
onDraw = {
// Background Arc
drawArc(
color = Gray100,
startAngle = startAngle,
sweepAngle = limitAngle,
useCenter = false,
style = Stroke(thickness.toPx(), cap = StrokeCap.Square),
size = Size(size.width, size.height)
)
// Foreground Arc
drawArc(
color = Green500,
startAngle = startAngle,
sweepAngle = sweepAngle.value,
useCenter = false,
style = Stroke(thickness.toPx(), cap = StrokeCap.Square),
size = Size(size.width, size.height)
)
}
)
Text(
text = level,
modifier = Modifier
.fillMaxWidth(0.125f)
.align(Alignment.Center)
.offset(y = (-10).dp),
color = Color.White,
fontSize = 82.sp
)
Text(
text = "LEVEL",
modifier = Modifier
.padding(bottom = 8.dp)
.align(Alignment.BottomCenter),
color = Color.White,
fontSize = 20.sp
)
}
}
如果进度百分比超过100%,我如何重新开始动画,就像gif中的那个。有人有什么想法吗?谢谢!
2条答案
按热度按时间lkaoscv71#
我的第一个答案感觉不像是在做任何公正的事情,因为它与你发布的显示你想要什么的gif相去甚远。
这是另一个非常类似的实现。但是,我觉得这个实现在调用动画序列方面效率不是很高,但是在
re-composition
方面,我加入了一些称为deferred reading的优化策略。确保只有遵守这些值的可组合体是将被重新组合的唯一部分。我在可组合的父进程中留下了一个Log
语句来验证它,当进程动画时,ArcProgressbar
没有进行不必要的更新。完整的源代码,您可以复制和粘贴(* 最好在一个单独的文件 *)没有任何问题。
样品使用:
第一次
nc1teljy2#
我在你的代码中做了一些修改来利用
Animatable
,所以我们总是在动画到target
值之前先从snap
开始。我们还消除了这里的计算,因为我们只想在每次分数更新时填充整个进程,在我们的情况下是300(limitAngle
),并使用newScore
状态作为LaunchedEffect
中的key
,以便在每次递增时触发动画。它只是一个任意值,您可以在不影响动画的情况下对其进行更改。样品使用: