Reputation: 1106
How can I change the ripple color of an IconButton?
I tried doing it this way, but it doesn't change:
IconButton(
onClick = { onClick() },
modifier = Modifier.clickable(
onClick = { onClick() },
indication = rememberRipple(color = MyCustomTheme.colors.primary),
interactionSource = remember { MutableInteractionSource() },
)
)
Upvotes: 32
Views: 30423
Reputation: 516
androidx.compose.material3:material3:1.3.0+
@OptIn(ExperimentalMaterial3Api::class)
private val MyRippleConfiguration = RippleConfiguration(
color = Color.Red,
rippleAlpha = RippleAlpha(
draggedAlpha = 1f,
focusedAlpha = 1f,
hoveredAlpha = 1f,
pressedAlpha = 0.2f
)
)
and use it in your theme :
MaterialTheme(
colorScheme = colorScheme,
typography = Typography
) {
CompositionLocalProvider(LocalRippleConfiguration provides MyRippleConfiguration) {
content()
}
}
Upvotes: 0
Reputation: 41
I'm using "androidx.compose.material:material:1.7.5"
Here is how I implemented it:
// for my custom components with Modifier.clickable {}
val myRipple = ripple(color = Color.White)
val myAlpha = RippleAlpha(0.16f, 0.1f, 0.08f, 0.5f)
// for native clickable components like Button()
@OptIn(ExperimentalMaterialApi::class)
val rippleConfiguration = RippleConfiguration(color = Color.White, rippleAlpha = myAlpha )
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun MyAppTheme(content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalIndication provides myRipple, LocalRippleConfiguration provides myConfiguration
) {
content()
}
}
Upvotes: 0
Reputation: 1194
Since version 1.3.0
of the androidx.compose.material3:material3 library, RippleTheme is deprecated. The new way to provide ripple customisations looks like this:
@OptIn(ExperimentalMaterialApi::class)
private val MyRippleConfiguration =
RippleConfiguration(color = Color.Red, rippleAlpha = MyRippleAlpha)
CompositionLocalProvider(LocalRippleConfiguration provides MyRippleConfiguration) {
Button {
// ...
}
}
See the Migrate to Indication and Ripple APIs Android Developers' guide for more info.
Upvotes: 5
Reputation: 365008
Your code doesn't work since the Ripple is implemented in a .clickable
modifier defined inside the IconButton
.
The appearance of the Ripple is based on a RippleTheme
. You can define a custom RippleTheme
and apply it to your composable with LocalRippleTheme
.
Something like:
private object RippleCustomTheme: RippleTheme {
//Your custom implementation...
@Composable
override fun defaultColor() =
RippleTheme.defaultRippleColor(
Color.Red,
lightTheme = true
)
@Composable
override fun rippleAlpha(): RippleAlpha =
RippleTheme.defaultRippleAlpha(
Color.Black,
lightTheme = true
)
}
and:
CompositionLocalProvider(LocalRippleTheme provides RippleCustomTheme) {
IconButton(
onClick = { },
) {
Icon(Icons.Filled.Add, "")
}
}
Upvotes: 26
Reputation: 4909
If you need just to override ripple color in one place you can create your own modifier for it.
fun Modifier.clickable(
rippleColor: Color? = null,
onClick: () -> Unit
) = composed(
inspectorInfo = debugInspectorInfo {
name = "clickable"
properties["rippleColor"] = rippleColor
properties["onClick"] = onClick
}
) {
Modifier.clickable(
onClick = onClick,
indication = rippleColor?.let {
rememberRipple(
color = it
)
} ?: LocalIndication.current,
interactionSource = remember { MutableInteractionSource() }
)
}
Upvotes: 5
Reputation: 448
It's a bit late, but maybe this code will help someone.
To make your code work you need to apply interactionSource to the button itself too.
You can change the color locally in this way. It is important to apply height after calling the indication in order to keep the correct button and ripple dimensions.
Additionally, you need to apply a radius of any size in order to contain the radius inside of the button's shape (this seems to be a bug in Compose 1.2.0-rc03.
val interactionSource = remember { MutableInteractionSource() }
val rippleColor = Color.RED
val shape = RoundedCornerShape(size = 16.dp)
Button(
modifier = Modifier
.clip(shape = shape)
.indication(
interactionSource = interactionSource,
indication = rememberRipple(
color = rippleColor,
radius = 8.dp
)
)
.height(height = 40.dp),
shape = shape,
interactionSource = interactionSource,
)
Upvotes: 10
Reputation: 620
I don't know if you found a way to make it work for the whole app but I found a way to do so. So I'm posting this incase someone else has a similar issue.
You can set the custom RippleTheme
object as described by Gabriele Mariotti's answer then you can pass the CompositionLocalProvider()
as content in MaterialTheme. The content from the app's theme
can then be set as content for CompositionalLocalProvider()
.
Take a look here:
private object JetNewsRippleTheme : RippleTheme {
// Here you should return the ripple color you want
// and not use the defaultRippleColor extension on RippleTheme.
// Using that will override the ripple color set in DarkMode
// or when you set light parameter to false
@Composable
override fun defaultColor(): Color = MaterialTheme.colors.primary
@Composable
override fun rippleAlpha(): RippleAlpha = RippleTheme.defaultRippleAlpha(
Color.Black,
lightTheme = !isSystemInDarkTheme()
)
}
Then for your app theme it should be:
@Composable
fun JetNewsTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
MaterialTheme(
colors = if (darkTheme) DarkColors else LightColors,
typography = JetNewsTypography,
shapes = JetNewsShapes
) {
CompositionLocalProvider(
LocalRippleTheme provides JetNewsRippleTheme,
content = content
)
}
}
This method should work for the whole app unless you explicitly set another RippleTheme
directly to Composables below the AppTheme
hierarchy. And it doesn't conflict with other types of ComposableLocalProvider
values you may set directly to your other Composables
.
Upvotes: 47