2021年5月9日日曜日

Jetpack Compose : Canvas Composable を使う

View の onDraw() で描画して Custom View を作る、というのを Compose でやりたいときは Canvas Composable を使います。

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 件のコメント:

コメントを投稿