Search code examples
android-jetpack-composeandroid-jetpack-compose-material3android-jetpack-compose-button

How do I set the ripple colour of my button to one of the colours in my theme now that "RippleTheme" is deprecated?


My app's theme has a primary colour of green and that's the colour that is chosen for the ripple effect in buttons in my app by default.

In a particular button within my app, I want the ripple effect to have the theme's onSurface colour to match the colour of the button's outline and text. I achieved this previously by means of LocalRippleTheme and RippleTheme, as follows:

CompositionLocalProvider(LocalRippleTheme provides MyRippleTheme) {
    OutlinedButton(border = BorderStroke(1.dp, MaterialTheme.colorScheme.onSurface)) {
        Text(color = MaterialTheme.colorScheme.onSurface)
    }
}

object MyRippleTheme : RippleTheme {

    @Composable
    override fun defaultColor() =
        RippleTheme.defaultRippleColor(MaterialTheme.colorScheme.onSurface, lightTheme = true)

    @Composable
    override fun rippleAlpha(): RippleAlpha =
        RippleTheme.defaultRippleAlpha(MaterialTheme.colorScheme.onSurface, lightTheme = true)
}

With the release of version 1.7.0 of the androidx.compose.material:material-ripple library, it's now an error to use LocalRippleTheme and RippleTheme. How do I set the ripple colour of my button to the onSurface colour in my app's theme now that LocalRippleTheme and RippleTheme are deprecated?


Solution

  • Direct answer to the question

    The guidance in the Migrate from Ripple Theme > Using RippleTheme to change the color/alpha of a ripple for a given component Android Developers' documentation is to use LocalRippleConfiguration and RippleConfiguration instead of LocalRippleTheme and RippleTheme. I've managed to adapt the code example in that guidance ever-so-slightly so that it uses MaterialTheme.colorScheme.onSurface instead of a hardcoded colour, as follows:

    CompositionLocalProvider(LocalRippleConfiguration provides RippleConfiguration(MaterialTheme.colorScheme.onSurface)) {
        OutlinedButton(border = BorderStroke(1.dp, MaterialTheme.colorScheme.onSurface)) {
            Text(color = MaterialTheme.colorScheme.onSurface)
        }
    }
    

    This works. The ripple appears the same as before. One caveat with this approach that I can see is that the RippleConfiguration constructor is called every time my button is pressed. I don't know enough about Jetpack Compose to say whether this is a bad thing or a not-bad thing. If it is a bad thing, please add a comment explaining why 🙏

    Alternative answer to the question

    Instead of setting the color of the Text item within the button, set the contentColor of the button instead, as below. The ripple effect will then have a colour which matches the colour of the text and you don't need to define an override for the ripple effect.

    OutlinedButton(
        colors = ButtonDefaults.outlinedButtonColors(
            containerColor = MaterialTheme.colorScheme.surface,
            contentColor = MaterialTheme.colorScheme.onSurface
        )
        border = BorderStroke(1.dp, MaterialTheme.colorScheme.onSurface)
    ) {
        Text(text = "Tap me")
    }