androidandroid-jetpack-composeandroid-jetpack-compose-surface

Jetpack Compose Surface click ripple is not clipped based on shape?


I have 3 Surfaces as can be seen in gif when i click ripple effect propagates without taking the shapes of Surfaces into consideration.

enter image description here

Which are created with

@Composable
fun SurfaceClickPropagationExample() {

    // Provides a Context that can be used by Android applications
    val context = AmbientContext.current

    // 🔥 Offset moves a component in x and y axes which can be either positive or negative
    // 🔥🔥 When a component inside surface is offset from original position it gets clipped.
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .wrapContentHeight()
            .clipToBounds()
            .clickable(onClick = {})
    ) {

        Surface(
            modifier = Modifier
                .preferredSize(150.dp)
                .padding(12.dp)
                .clickable(onClick = {
                })
                .clipToBounds(),
            elevation = 10.dp,
            shape = RoundedCornerShape(10.dp),
            color = (Color(0xFFFDD835))
        ) {

            Surface(
                modifier = Modifier
                    .preferredSize(80.dp)
                    .clipToBounds()
                    .offset(x = 50.dp, y = (-20).dp)
                    .clickable(onClick = {
                    }),
                elevation = 12.dp,
                shape = CircleShape,
                color = (Color(0xFF26C6DA))
            ) {

            }
        }

        Surface(
            modifier = Modifier
                .preferredSize(110.dp)
                .padding(12.dp)
                .offset(x = 110.dp, y = 20.dp)
                .clickable(onClick = {}),
            shape = CutCornerShape(10.dp),
            color = (Color(0xFFF4511E)),
            elevation = 8.dp
        ) {}
    }
}

I added Modifier.clipToBounds() to check if it works with it, but it does not work with or without it.


Solution

  • Update for compose version 1.0.0-beta08:

    Use the new experimental overload of Surface that accepts onClick.

    @ExperimentalMaterialApi
    @Composable
    fun Surface(
        onClick: () -> Unit,
        modifier: Modifier = Modifier,
        shape: Shape = RectangleShape,
        color: Color = MaterialTheme.colors.surface,
        contentColor: Color = contentColorFor(color),
        border: BorderStroke? = null,
        elevation: Dp = 0.dp,
        interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
        indication: Indication? = LocalIndication.current,
        enabled: Boolean = true,
        onClickLabel: String? = null,
        role: Role? = null,
        content: () -> Unit
    ): @ExperimentalMaterialApi @Composable Unit
    

    Documentation


    Try applying Modifier.clip(shape: Shape) before Modifier.clickable.

    When using Modifiers in compose, the order matters. Modifier elements that appear first will be applied first. (documentation)