How to disable ripple effect when clicking in Jetpack Compose

Viewed 18306

In Jetpack Compose, when you enable clickable {} on a modifier for a composable, by default it enables ripple effect for it. How to disable this behavior?

Example code

Row(modifier = Modifier
         .clickable { // action }
)
4 Answers

Short answer:
to disable the ripple pass null in the indication parameter in the clickable modifier:

val interactionSource = remember { MutableInteractionSource() }
Column {
    Text(
        text = "Click me and my neighbour will indicate as well!",
        modifier = Modifier
            .clickable(
                interactionSource = interactionSource,
                indication = null
            ) {
                /* .... */
            }
    )

Long answer:
If you add the clickable modifier to the element to make it clickable within its bounds it will show an Indication as specified in indication parameter.

By default, indication from LocalIndication will be used.

If you are using a MaterialTheme in your hierarchy, a Ripple will be used as the default Indication inside components such as androidx.compose.foundation.clickable and androidx.compose.foundation.indication.

Why it doesn't work with some Composables

Pls note that in some Composables, like Button or IconButton, it doesn't work since the indication is defined internally by the component which uses indication = rememberRipple(). This creates and remembers a Ripple using values provided by RippleTheme.

In this cases you can't disable it but you can change the appearance of the ripple that is based on a RippleTheme. You can define a custom RippleTheme and apply it to your composable with the LocalRippleTheme.

Something like:

CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
    Button(
        onClick = { /*...*/ },
    ) {
       //...
    }
}

with:

private object NoRippleTheme : RippleTheme {
    @Composable
    override fun defaultColor() = Color.Unspecified

    @Composable
    override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f,0.0f,0.0f,0.0f)
}

Use this Modifier extension:

inline fun Modifier.noRippleClickable(crossinline onClick: ()->Unit): Modifier = composed {
    clickable(indication = null,
        interactionSource = remember { MutableInteractionSource() }) {
        onClick()
    }
}

then simply replace Modifier.clickable {} with Modifier.noRippleClickable {}

Row(modifier = Modifier.noRippleClickable { 
  // action 
})

To disable the ripple effect, have to pass null to indication property of the modifier.

More about indication on Jetpack Compose documentation

Code

Row(
    modifier = Modifier
        .clickable(
            indication = null, 
            interactionSource = remember { MutableInteractionSource() } // This is mandatory
        ) { 
            // action
        }
)

Modifier extension with other parameters :

inline fun Modifier.noRippleClickable(
        enabled: Boolean = true,
        onClickLabel: String? = null,
        role: Role? = null,
        crossinline onClick: ()->Unit
    ): Modifier = composed {
        clickable(
            enabled = enabled,
            indication = null,
            onClickLabel = onClickLabel,
            role = role,
            interactionSource = remember { MutableInteractionSource() }) {
            onClick()
        }
    }
Related