I'm beginner in jetpack compose, especially in Canvas.
I want to create this with Canvas:
But I don't know how. I could create curved Text but with fillMaxSize and it's not useful for me. Because I want to use this picture as a button in a page and I have some buttons like this one in one page. So I want to have this Canvas with wrapcontent size. So how can I create that?
The answer mentioned in the comments above is mine. I did some adjustments in order to give you some direction. The code is listed below:
@Composable
fun ButtonWithCurvedText(
@DrawableRes icon: Int,
text: String,
iconSize: Dp,
onClick: () -> Unit,
) {
val density = LocalDensity.current
val imgSize = iconSize
val imageSizePx = with(density) { imgSize.toPx() }
val labelSize = 12.sp
val textToIconPadding = 4.dp
val textToIconPaddingPx = with(density) { textToIconPadding.toPx() }
val boxSize = imgSize + (textToIconPadding * 2) + with(density) { labelSize.roundToPx().toDp() }
val boxSizePx = with(density) { boxSize.toPx() }
val imageInset = ((boxSize - imgSize) / 2)
val imageInsetPx = with(density) { imageInset.toPx() }
val arcTop = imageInsetPx - (textToIconPaddingPx / 2f)
val arcLeft = imageInsetPx - (textToIconPaddingPx / 2f)
val arcBottom = boxSizePx - imageInsetPx + (textToIconPaddingPx / 2f)
val arcRight = boxSizePx - imageInsetPx + (textToIconPaddingPx / 2f)
val vectorPainter = rememberVectorPainter(
ImageVector.vectorResource(icon)
)
Canvas(
modifier = Modifier
.size(boxSize)
.background(Color.Gray)
.clickable {
onClick()
}
) {
drawCircle(Color.LightGray, radius = imageSizePx / 2f)
with(vectorPainter) {
inset(
horizontal = imageInsetPx,
vertical = imageInsetPx
) {
draw(Size(imageSizePx, imageSizePx))
}
}
drawIntoCanvas {
val path = Path().apply {
addArc(arcLeft, arcTop, arcRight, arcBottom, 270f, 180f)
}
it.nativeCanvas.drawTextOnPath(
text,
path,
0f,
0f,
Paint().apply {
textSize = labelSize.toPx()
textAlign = Paint.Align.CENTER
}
)
}
}
}
As you mentioned, you want something responsive. You just need to make some constants used here as parameters. The only "size" param required here is the icon size. You can use like this:
Row() {
ButtonWithCurvedText(R.drawable.ic_share, "Share", 48.dp, {})
ButtonWithCurvedText(R.drawable.ic_cancel, "Cancel", 72.dp, {})
ButtonWithCurvedText(R.drawable.ic_check, "Check", 96.dp, {})
}
The result is like below: