Skip to content

Instantly share code, notes, and snippets.

@Jaseemakhtar
Created December 5, 2021 04:21
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jaseemakhtar/3746ce9dbbb28905658b0b2142ea2c54 to your computer and use it in GitHub Desktop.
Save Jaseemakhtar/3746ce9dbbb28905658b0b2142ea2c54 to your computer and use it in GitHub Desktop.
Android Jetpack Compose Custom menu, which align items in circular fashion.
@Composable
fun CircularRevealMenu(
modifier: Modifier,
contentPadding: Dp = 16.dp,
circleRadius: () -> Float,
content: @Composable () -> Unit
) {
val configuration = LocalConfiguration.current
Layout(content = content, modifier = modifier) { children, constraints ->
val screenWidth = configuration.screenWidthDp.dp.toPx() * circleRadius()
val placeables = children.map { it.measure(constraints) }
val maxItemHeight = placeables.maxOf {
it.height
}
val maxItemWidth = placeables.maxOf {
it.width
}
val gap = 90 / placeables.size
val radiusOffset = (max(maxItemHeight, maxItemWidth) / 2) + contentPadding.toPx()
val radius = screenWidth - radiusOffset
val offset = 180 - gap / 2f
layout(screenWidth.toInt(), screenWidth.toInt()) {
for (i in placeables.indices) {
val radians = Math.toRadians((offset - (gap * i)).toDouble())
placeables[i].placeRelative(
x = (cos(radians) * radius + screenWidth).toInt() - placeables[i].width / 2,
y = (sin(radians) * radius + 0).toInt() - placeables[i].height / 2
)
}
}
}
}
enum class CircularMenuStates { Collapsed, Expanded }
@Preview(showBackground = true)
@Composable
fun PreviewCircularMenu() {
CircularRevealMenu(modifier = Modifier, circleRadius = { 1f }) {
Text(text = "Item 1")
Text(text = "Item 2")
Text(text = "Item 3")
Text(text = "Item 4")
}
}
@Jaseemakhtar
Copy link
Author

Jaseemakhtar commented Dec 5, 2021

Demo app here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment