DEV Community

Discussion on: Jetpack Compose — Reveal effect

Collapse
 
mr3ytheprogrammer profile image
M R 3 Y • Edited

Why all that Unnecessary complexity? I've created the same effect in a much more simple implementation

@Composable
fun CircularRevealLayout(
    modifier: Modifier = Modifier,
    isLightTheme: Boolean = !isSystemInDarkTheme()
) {
    var isLight by remember { mutableStateOf(isLightTheme) }
    var radius by remember { mutableStateOf(0f) }
    Box(
        modifier = modifier
            .fillMaxSize()
            .background(Color.Transparent)
            .drawBehind {
                drawCircle(
                    color = if (isLight) Color.White else Color.Black.copy(0.7f),
                    radius = radius,
                    center = Offset(size.width, 0f),
                )
            },
        contentAlignment = Alignment.Center
    ) {
        SwitchButton(
            modifier = Modifier
                .size(72.dp, 48.dp)
                .semantics {
                    contentDescription =
                        if (isLight) "Switch to dark theme" else "Switch to light theme"
                },
            checked = !isLight,
            onCheckedChange = { isLight = !isLight }
        )
    }
    val animatedRadius = remember { Animatable(0f) }
    val (width, height) = with(LocalConfiguration.current) {
        with(LocalDensity.current) { screenWidthDp.dp.toPx() to screenHeightDp.dp.toPx() }
    }
    val maxRadiusPx = hypot(width, height)
    LaunchedEffect(isLight) {
        animatedRadius.animateTo(maxRadiusPx, animationSpec = tween()) {
            radius = value
        }
        // reset the initial value after finishing animation
        animatedRadius.snapTo(0f)
    }
}

@Composable
fun SwitchButton(
    checked: Boolean,
    modifier: Modifier = Modifier,
    onCheckedChange: () -> Unit
) {
    Switch(
        checked = checked,
        modifier = modifier,
        onCheckedChange = { onCheckedChange() }
    )
}

@Preview(widthDp = 360, heightDp = 640)
@Composable
fun CircularRevealLayoutPreview() {
    CircularRevealLayout()
}
Enter fullscreen mode Exit fullscreen mode

Produces the following Result:

Result

Also, it can be easily extended to change the colors of system bars (status bar & navigation bar)

Collapse
 
bmonjoie profile image
Benjamin Monjoie

Sorry, I was not notified about your comment and I have just seen it now.

You didn't produce the same effect at all.
With my code, your toggle would still be grey in light mode and become green only where the circle shape is already overlaying it.

It might not be that obvious but if you look closely to the GIF at the top of the article, the text doesn't transition to white entirely in one go but only the parts where the ripple as already reached it are white and the other parts are still black.

I'm not sure I'm making myself completely clear but feel free to ask if that is not the case