@Composable
fun InfiniteLoadingSpinner(
modifier: Modifier = Modifier,
primaryColor: Color = MaterialTheme.colorScheme.primary,
backgroundColor: Color = primaryColor.copy(alpha = 0.2f),
sweepAngle: Float = 90f,
size: Dp = 350.dp,
strokeWidth: Dp = 45.dp
) {
val infiniteTransition = rememberInfiniteTransition()
val rotation by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 1200, easing = LinearEasing)
)
)
Box(
modifier = modifier
.size(size)
.aspectRatio(1f)
) {
Canvas(modifier = Modifier.fillMaxSize()) {
val halfStroke = strokeWidth.toPx() / 2
val rect = Rect(
left = halfStroke,
top = halfStroke,
right = size.toPx() - halfStroke,
bottom = size.toPx() - halfStroke
)
// 绘制背景环
drawCircle(
color = backgroundColor,
radius = size.toPx() / 2 - halfStroke,
style = Stroke(strokeWidth.toPx())
)
// 绘制主色进度弧
drawArc(
color = primaryColor,
startAngle = rotation - 90,
sweepAngle = sweepAngle.coerceIn(0f, 360f),
useCenter = false,
style = Stroke(width = strokeWidth.toPx(), cap = StrokeCap.Round),
topLeft = Offset(rect.left, rect.top),
size = Size(rect.width, rect.height)
)
}
}
}
使用
InfiniteLoadingSpinner(
primaryColor = Color_Primary_Red,
backgroundColor = Color_000000_10,
sweepAngle = 45f, // 主色弧占120度
size = 350.dp,
strokeWidth = 45.dp
)