Last active
May 22, 2024 15:16
-
-
Save icai/dde5067dbeabc7ca28189bb5cc01e958 to your computer and use it in GitHub Desktop.
CuSwitch.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun CustomSwitch( | |
checked: Boolean, | |
onCheckedChange: (Boolean) -> Unit, | |
modifier: Modifier = Modifier, | |
trackColor: Color = VoicenotifyTheme.colorScheme.primary, | |
thumbColor: Color = Color.White, | |
innerCircleColor: Color = Color.Gray, | |
animationDuration: Int = 300 | |
) { | |
val thumbRadius = 16.dp | |
val trackWidth = 48.dp | |
val trackHeight = 32.dp | |
val trackRadius = trackHeight / 2 | |
val thumbPosition = remember { Animatable(if (checked) 1f else 0f) } | |
val innerCircleRadius = remember { Animatable(thumbRadius.value * 0.5f) } | |
LaunchedEffect(checked) { | |
thumbPosition.animateTo( | |
if (checked) 1f else 0f, | |
animationSpec = tween(durationMillis = animationDuration) | |
) | |
innerCircleRadius.animateTo( | |
if (checked) thumbRadius.value * 0.75f else thumbRadius.value * 0.5f, | |
animationSpec = tween(durationMillis = animationDuration) | |
) | |
} | |
Canvas( | |
modifier = modifier | |
.size(trackWidth, trackHeight) | |
.pointerInput(Unit) { | |
detectTapGestures { | |
onCheckedChange(!checked) | |
} | |
} | |
) { | |
// Draw track | |
drawRoundRect( | |
color = trackColor.copy(alpha = 0.5f), | |
size = size, | |
cornerRadius = CornerRadius(x = trackRadius.toPx(), y = trackRadius.toPx()) | |
) | |
// Draw thumb | |
val thumbOffsetX = thumbPosition.value * (size.width - thumbRadius.toPx() * 2) | |
val thumbCenter = Offset(x = thumbOffsetX + thumbRadius.toPx(), y = size.height / 2) | |
drawCircle( | |
color = thumbColor, | |
radius = thumbRadius.toPx(), | |
center = thumbCenter, | |
style = Fill | |
) | |
// Draw inner circle | |
drawCircle( | |
color = innerCircleColor, | |
radius = innerCircleRadius.value.dp.toPx(), | |
center = thumbCenter, | |
style = Fill | |
) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
private fun CuSwitch( | |
modifier: Modifier = Modifier, | |
checked: MutableState<Boolean> = remember { mutableStateOf(false) }, | |
onCheckedChange: (Boolean) -> Unit = {} | |
) { | |
val width = 34.dp | |
val height = 19.dp | |
val gapBetweenThumbAndTrackEdge = 2.dp | |
// 4 15 + | |
val thumbRadius = (height / 2) - gapBetweenThumbAndTrackEdge | |
val animatePosition = animateFloatAsState( | |
targetValue = if (checked.value) { | |
with(LocalDensity.current) { (width - thumbRadius - gapBetweenThumbAndTrackEdge).toPx() } | |
} else { | |
with (LocalDensity.current) { (thumbRadius + gapBetweenThumbAndTrackEdge).toPx() } | |
} | |
) | |
val checkedThumbColor = VoicenotifyTheme.colors.colorOnCustom | |
val uncheckedThumbColor = VoicenotifyTheme.colors.colorThumbOffCustom | |
val checkedTrackColor = VoicenotifyTheme.colors.colorPrimary | |
val uncheckedTrackColor = VoicenotifyTheme.colors.colorOffCustom | |
Canvas( | |
modifier = modifier | |
.size(width = width, height = height) | |
.pointerInput(Unit) { | |
detectTapGestures( | |
onTap = { | |
checked.value = !checked.value | |
onCheckedChange(checked.value) | |
} | |
) | |
} | |
) { | |
drawRoundRect( | |
color = if (checked.value) checkedTrackColor else uncheckedTrackColor, | |
cornerRadius = CornerRadius(x = 10.dp.toPx(), y = 10.dp.toPx()) | |
) | |
drawCircle( | |
color = if (checked.value) checkedThumbColor else uncheckedThumbColor, | |
radius = thumbRadius.toPx(), | |
center = Offset( | |
x = animatePosition.value, | |
y = size.height / 2 | |
) | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment