Jetpack Compose-进度条及圆形进度条绘制

前言

自带的组件

效果1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Preview
@Composable
fun ProgressBarPreview() {
Column(
Modifier
.width(120.dp)
.wrapContentHeight()
.padding(16.dp)
.background(Color.White)
) {
// 圆形不确定进度条
CircularProgressIndicator(
progress = { 0.75f },
modifier = Modifier.padding(16.dp),
color = ProgressIndicatorDefaults.circularColor,
strokeWidth = ProgressIndicatorDefaults.CircularStrokeWidth,
trackColor = Color(0xffCCE7FF),
strokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap,
gapSize = 8.dp
)


// 线性确定进度条
LinearProgressIndicator(
progress = { 0.75f },
modifier = Modifier.padding(16.dp),
color = ProgressIndicatorDefaults.linearColor,
trackColor = ProgressIndicatorDefaults.linearTrackColor,
strokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
)
}
}

效果

image-20250821092949770

效果2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Preview
@Composable
fun ProgressBarPreview() {
Column(
Modifier
.width(120.dp)
.wrapContentHeight()
.padding(16.dp)
.background(Color.White)
) {
// 圆形不确定进度条
CircularProgressIndicator(
progress = { 0.75f },
modifier = Modifier.padding(10.dp),
color = Color(0xFF0085F7),
strokeWidth = ProgressIndicatorDefaults.CircularStrokeWidth,
trackColor = Color(0xffCCE7FF),
strokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap,
gapSize = 0.dp
)


// 线性确定进度条
LinearProgressIndicator(
progress = { 0.75f },
modifier = Modifier.padding(10.dp),
color = Color(0xFF0085F7),
trackColor = Color(0xffCCE7FF),
strokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
gapSize = 0.dp
)
}
}

效果

image-20250821093544924

去除结尾圆点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Box(
Modifier
.width(120.dp)
.height(8.dp)
) {
LinearProgressIndicator(
progress = { 0.75f },
modifier = Modifier.fillMaxSize(),
color = Color(0xFF0085F7),
trackColor = Color(0xffCCE7FF),
gapSize = 0.dp,
drawStopIndicator = {}
)
}

效果

image-20250821094444445

自定义组件

自带的效果不满足我们的要求,所以这里自定义组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Box
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.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

/**
* 自定义圆形进度条组件
*
* @param progress 进度值,范围 0f-1f
* @param modifier 修饰符
* @param size 进度条大小
* @param strokeWidth 进度条线宽
* @param backgroundColor 背景圆环颜色
* @param progressColor 进度圆环颜色
* @param strokeCap 线帽样式
*/
@Composable
fun CircularProgressBar(
progress: Float,
modifier: Modifier = Modifier,
size: Dp = 48.dp,
backgroundWidth: Dp = 4.dp,
strokeWidth: Dp = 8.dp,
startAngle: Float = -90f,
backgroundColor: Color = Color.Transparent,
progressColor: Color = Color.Blue,
strokeCap: StrokeCap = StrokeCap.Round
) {
// 确保进度在 0f 到 1f 之间
val clampedProgress = progress.coerceIn(0f, 1f)

Canvas(
modifier = modifier.size(size)
) {
// 绘制背景圆环
drawArc(
color = backgroundColor,
startAngle = 0f,
sweepAngle = 360f,
useCenter = false,
style = Stroke(
width = backgroundWidth.toPx(),
cap = strokeCap
),
size = Size(size.toPx(), size.toPx()),
topLeft = Offset.Zero
)

// 绘制进度圆环 (360度 * 进度)
drawArc(
color = progressColor,
startAngle = startAngle, // 从顶部开始
sweepAngle = 360f * clampedProgress,
useCenter = false,
style = Stroke(
width = strokeWidth.toPx(),
cap = strokeCap
),
size = Size(size.toPx(), size.toPx()),
topLeft = Offset.Zero
)
}
}

@Preview
@Composable
fun CircularProgressBarPreview() {
Box(Modifier.padding(16.dp)) {
CircularProgressBar(
progress = 0.75f,
size = 80.dp,
strokeWidth = 8.dp,
progressColor = Color(0xFF0085F7),
backgroundColor = Color(0xffCCE7FF),
)
}

}

效果

image-20250821091851808