Canvas に渡す onDraw lamnda は Receiver が DrawScope になっています。
DrawScope からは描画エリアの大きさとして size: Size が取れます。
また、DrawScope は Density を継承しているので、Dp.toPx() とかも呼び出せます。
@Composable
fun CircleProgress(
progress: Int,
modifier: Modifier,
colorProgress: Color = MaterialTheme.colors.primary,
colorBackground: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f)
.compositeOver(MaterialTheme.colors.surface),
strokeWidth: Dp = 8.dp,
) {
Canvas(modifier = modifier) {
val stroke = Stroke(width = strokeWidth.toPx(), cap = StrokeCap.Round)
val diameter = min(size.width, size.height) - stroke.width
val topLeft = Offset((size.width - diameter) / 2, (size.height - diameter) / 2)
val circleSize = Size(diameter, diameter)
drawArc(
color = colorBackground,
startAngle = -90f,
sweepAngle = 360f,
useCenter = false,
style = stroke,
topLeft = topLeft,
size = circleSize,
)
drawArc(
color = colorProgress,
startAngle = -90f,
sweepAngle = 360f / 100 * progress,
useCenter = false,
style = stroke,
topLeft = topLeft,
size = circleSize,
)
}
}
@Preview
@Composable
fun CircleProgressPreview() {
var progress by remember { mutableStateOf(0) }
val animateProgress by animateIntAsState(targetValue = progress, animationSpec = tween())
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(16.dp)
) {
Button(onClick = {
progress = Random.nextInt(0, 101)
}) {
Text("Change Progress")
}
Spacer(modifier = Modifier.height(16.dp))
CircleProgress(
progress = animateProgress,
modifier = Modifier.size(120.dp)
)
}
}
animate**AsState などでアニメーションも簡単にできます。
0 件のコメント:
コメントを投稿