Add ripple effect to a custom gesture in Jetpack Compose

Issue

I try to create a tappable surface in Jetpack Compose where the elevation changes when the user taps the surface. The following code already works:

var tapped by remember { mutableStateOf(false) }
val elevation by animateDpAsState(
    targetValue  if (tapped) 0.dp else 5.dp,
    animationSpec  tween(50)
)

Surface(
    shape  RoundedCornerShape(20.dp),
    modifier  Modifier
         .padding(16.dp)
         .requiredSize(150.dp)
         .pointerInput(Unit) {
              detectTapGestures(onPress  {
              tapped  true

              tryAwaitRelease()

              tapped  false
         })
    },
    elevation  elevation
) {
  ...
}

However I would like to have a ripple effect during the tap. How could I achieve this?

The default button/surface onClick and clickable is not suitable because it only handles press inputs but no taps.

Solution

You use Modifier.indication) to add ripple effect, and pass events with interactionSource to update it state like this:

var tapped by remember { mutableStateOf(false) }
val interactionSource  remember { MutableInteractionSource() }

Surface(
    modifier  Modifier
        .indication(interactionSource, LocalIndication.current)
        .pointerInput(Unit) {
            detectTapGestures(onPress  { offset ->
                tapped  true

                val press  PressInteraction.Press(offset)
                interactionSource.emit(press)

                tryAwaitRelease()

                interactionSource.emit(PressInteraction.Release(press))

                tapped  false
            })
        }
) {
}

Answered By – Philip Dukhov

Leave a Comment