Jetpack Compose 中如何实现矩形类进度条动画及启停控制
Jetpack Compose 进度条动画+启停控制实现方案
实现逻辑
- 封装独立的
ProgressBarState状态类,基于Compose自带的Animatable实现动画控制,天然支持进度平滑过渡、启停、重置能力 - 对外暴露
start、pause、reset三个核心控制方法,上层无需关心动画内部实现 - 替换原代码中硬编码的固定进度,绑定状态类中的实时进度值
完整实现代码
1. 定义状态控制类
import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.AnimationSpec import androidx.compose.animation.core.tween import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import kotlinx.coroutines.coroutineScope class ProgressBarState(initialProgress: Float = 0f) { val progress = Animatable(initialProgress) // 获取当前动画运行状态 val isRunning: Boolean get() = progress.isRunning /** * 启动进度动画 * @param targetProgress 目标进度,默认到100% * @param animationSpec 动画配置,可自定义时长、插值器等 */ suspend fun start( targetProgress: Float = 1f, animationSpec: AnimationSpec<Float> = tween(durationMillis = 3000) ) { progress.animateTo(targetProgress, animationSpec) } // 暂停当前动画 fun pause() { progress.stop() } // 重置进度为0 suspend fun reset() { progress.snapTo(0f) } } @Composable fun rememberProgressBarState(initialProgress: Float = 0f): ProgressBarState { return remember { ProgressBarState(initialProgress) } }
2. 修改原有ProgressBar组件
import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp val Pink80 = Color(0xFFEFB8C8) val Purple40 = Color(0xFF6650a4) @Composable fun ProgressBar( state: ProgressBarState, modifier: Modifier = Modifier.size(300.dp, 180.dp) ) { Canvas(modifier = modifier.fillMaxSize().padding(16.dp)) { val canvasWidth = size.width val canvasSize = size // 底部背景圆角矩形 drawRoundRect( color = Pink80, topLeft = Offset(x = 0F, y = 0F), size = Size(canvasSize.width, 55F), cornerRadius = CornerRadius(60F, 60F), ) // 进度圆角矩形,绑定实时进度值 drawRoundRect( color = Purple40, topLeft = Offset(x = 0F, y = 0F), size = Size(canvasWidth * state.progress.value , 55F), cornerRadius = CornerRadius(60F, 60F), ) } }
3. 上层调用示例
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch @Composable fun ProgressBarDemo() { val progressState = rememberProgressBarState() // 获取协程作用域,用于调用挂起方法 val scope = rememberCoroutineScope() Column( modifier = Modifier.padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(16.dp) ) { ProgressBar(state = progressState) Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { Button(onClick = { scope.launch { progressState.start() } }) { Text("启动动画") } Button(onClick = { progressState.pause() }) { Text("暂停动画") } Button(onClick = { scope.launch { progressState.reset() } }) { Text("重置进度") } } } }
可选调整说明
如果需要自定义动画效果,修改start方法的animationSpec参数即可,比如换成弹簧动画、调整动画时长、添加插值器都可以直接通过该参数配置。
内容的提问来源于stack exchange,提问作者Sharan
相关产品推荐
相关产品推荐

