Skip to content

Instantly share code, notes, and snippets.

@AndreVero
Last active April 15, 2024 07:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndreVero/45093510af867ca50825f0901078396d to your computer and use it in GitHub Desktop.
Save AndreVero/45093510af867ca50825f0901078396d to your computer and use it in GitHub Desktop.
Drawing items on custom layout
Layout(
modifier = modifier,
content = {
// Draw each item with appropriate information
repeat(items.size) { index ->
Box(modifier = Modifier.size(itemSize)) {
content(items[index])
}
}
}
) { measurables, constraints ->
val paddingInPx = itemPadding.toPx()
val placeables = measurables.map { measurable -> measurable.measure(constraints) }
val sizeInPx = size.toPx().toInt()
// We need to remove the itemSize because items will be positioned not in a circle but at the edge
val availableSpace = sizeInPx - itemSize.toPx()
val radius = (availableSpace / 2.0).roundToInt()
// Calculate the step between each item
val angleStep = (360 / items.size.toDouble()).degreesToRadians()
layout(
width = sizeInPx,
height = sizeInPx,
) {
placeables.forEachIndexed { index, placeable ->
// Calculate the angle of each item
val itemAngle = angleStep * index.toDouble()
// Get coordinates relative to the circle center with paddings
val offset = getCoordinates(
radius = radius.toDouble(),
angle = itemAngle,
paddings = paddingInPx
)
placeable.placeRelative(
x = offset.x.roundToInt(),
y = offset.y.roundToInt(),
)
}
}
}
}
private fun getCoordinates(angle: Double, radius: Double, paddings: Float): Offset {
val radiusWithPaddings = radius - paddings
val x = radiusWithPaddings * sin(angle)
val y = radiusWithPaddings * cos(angle)
// Adding radius is necessary to shift the origin from the center of the circle
return Offset(
x = x.toFloat() + radius.toFloat(),
y = y.toFloat() + radius.toFloat(),
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment