Skip to content

Instantly share code, notes, and snippets.

@ardakazanci
Created April 10, 2024 07:33
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 ardakazanci/e60f8262f038ba8d93f848eaa1c48143 to your computer and use it in GitHub Desktop.
Save ardakazanci/e60f8262f038ba8d93f848eaa1c48143 to your computer and use it in GitHub Desktop.
Circular Menu Group with Jetpack Compose
@Composable
fun CircularMenuGroup(
icons: List<ImageVector>,
baseRadius: Float,
modifier: Modifier = Modifier,
backgroundColor: Color = Color(0xFF21FA90),
shadowElevation: Dp = 4.dp
) {
var selectedIndex by remember { mutableIntStateOf(-1) }
var sizeSliderValue by remember { mutableFloatStateOf(1f) }
var paddingSliderValue by remember { mutableFloatStateOf(0f) }
var shapeSliderValue by remember { mutableFloatStateOf(0f) }
val iconSize = (40 * sizeSliderValue).dp
val radius = baseRadius + paddingSliderValue
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxWidth()
) {
val angleStep = 360f / icons.size
icons.forEachIndexed { index, icon ->
val angleInRadians = Math.toRadians((index * angleStep).toDouble())
val x = (radius * cos(angleInRadians)).toFloat() * sizeSliderValue
val y = (radius * sin(angleInRadians)).toFloat() * sizeSliderValue
val targetX = if (index == selectedIndex) 0.dp else x.dp
val targetY = if (index == selectedIndex) 0.dp else y.dp
val animatedX by animateDpAsState(
targetX,
animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy), label = "animatedX"
)
val animatedY by animateDpAsState(
targetY,
animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy), label = "animatedY"
)
Box(
modifier = Modifier
.offset(animatedX, animatedY)
.size(iconSize)
.shadow(
elevation = shadowElevation,
shape = RoundedCornerShape(percent = (shapeSliderValue * 50).toInt())
)
.background(
backgroundColor,
shape = RoundedCornerShape(percent = (shapeSliderValue * 50).toInt())
)
.clickable { selectedIndex = index },
contentAlignment = Alignment.Center
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = Color(0XFF424651),
modifier = Modifier.size(iconSize * 0.8f)
)
}
}
}
Spacer(modifier = Modifier.height(120.dp))
Column(
modifier = Modifier
.padding(horizontal = 16.dp)
) {
Slider(
value = sizeSliderValue,
onValueChange = { sizeSliderValue = it },
valueRange = 1f..2f,
modifier = Modifier.fillMaxWidth(),
colors = SliderDefaults.colors(
thumbColor = backgroundColor,
activeTrackColor = backgroundColor
)
)
Spacer(modifier = Modifier.height(8.dp))
Slider(
value = paddingSliderValue,
onValueChange = { paddingSliderValue = it },
valueRange = -50f..50f,
modifier = Modifier.fillMaxWidth(),
colors = SliderDefaults.colors(
thumbColor = backgroundColor,
activeTrackColor = backgroundColor
)
)
Spacer(modifier = Modifier.height(8.dp))
Slider(
value = shapeSliderValue,
onValueChange = { shapeSliderValue = it },
valueRange = 0f..1f,
modifier = Modifier.fillMaxWidth(),
colors = SliderDefaults.colors(
thumbColor = backgroundColor,
activeTrackColor = backgroundColor
)
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment