
Today, you will learn how to disable or remove the ripple effect in Android Jetpack Compose.
These are the 3 methods we will discuss:
- Using the Mutable Interaction Source
- Create a Custom MutableInteractionSource Class
- Create a Custom No Ripple Theme
For this article, create a MyUI() composable and call it inside the onCreate() method. We will write our code in it.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme {
Surface(
modifier = Modifier
.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
MyUI()
}
}
}
}
}
}
@Composable
fun MyUI() {
}
1. Using the Mutable Interaction Source:
You can use this method if you set the click listener using the Modifier.clickable method. For example, look at the Box below:
@Composable
fun MyUI() {
Box(
modifier = Modifier
.size(width = 72.dp, height = 36.dp)
.background(color = Color.Yellow)
.clickable {
// handle click events
},
contentAlignment = Alignment.Center
) {
Text(text = "Click Me")
}
}
Output:

Let’s disable the ripple. First, open the Modifier.clickable() signature.
fun Modifier.clickable(
interactionSource: MutableInteractionSource,
indication: Indication?,
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
)
We can disable the ripple using the interactionSource and indication parameters.
The MutableInteractionSource represents the stream of interactions corresponding to the events emitted by the component.
The Indication represents the visual effects that occur when certain interactions happen. For example, showing the ripple effect when a component is pressed. Set its value to null to remove the ripple.
@Composable
fun MyUI() {
val interactionSource = MutableInteractionSource()
Box(
modifier = Modifier
.size(width = 72.dp, height = 36.dp)
.background(color = Color.Yellow)
.clickable(
interactionSource = interactionSource,
indication = null
) {
// handle click events
},
contentAlignment = Alignment.Center
) {
Text(text = "Click Me")
}
}
Output:

2. Create a Custom MutableInteractionSource Class:
This method is helpful when the composable you are working with accepts MutableInteractionSource as the parameter. For example, Switch().
@Composable
fun MyUI() {
var checked by remember {
mutableStateOf(false)
}
Switch(
checked = checked,
onCheckedChange = {
checked = !checked
}
)
}
Output:

To disable the ripple, create a custom MutableInteractionSource Class.
class NoRippleInteractionSource : MutableInteractionSource {
override val interactions: Flow<Interaction> = emptyFlow()
override suspend fun emit(interaction: Interaction) {}
override fun tryEmit(interaction: Interaction) = true
}
Create an object of this class and pass it to the Switch.
@Composable
fun MyUI() {
var checked by remember {
mutableStateOf(false)
}
Switch(
checked = checked,
onCheckedChange = {
checked = !checked
},
interactionSource = NoRippleInteractionSource()
)
}
class NoRippleInteractionSource : MutableInteractionSource {
override val interactions: Flow<Interaction> = emptyFlow()
override suspend fun emit(interaction: Interaction) {}
override fun tryEmit(interaction: Interaction) = true
}
Output:

3. Create a Custom No Ripple Theme:
You can use this method when you want to disable the ripple on multiple composables.
Create a custom theme and remove the ripple color and alpha.
private object NoRippleTheme : RippleTheme {
@Composable
override fun defaultColor() = Color.Unspecified
@Composable
override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f,0.0f,0.0f,0.0f)
}
Apply it to the composables.
@Composable
fun MyUI() {
CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
// add your composables here
Box(
modifier = Modifier
.size(width = 72.dp, height = 36.dp)
.background(color = Color.Yellow)
.clickable {
// handle click events
},
contentAlignment = Alignment.Center
) {
Text(text = "Click Me")
}
}
}
private object NoRippleTheme : RippleTheme {
@Composable
override fun defaultColor() = Color.Unspecified
@Composable
override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f,0.0f,0.0f,0.0f)
}
Output:

How to Disable Ripple Effect on Jetpack Compose Button?
We can disable the ripple effect on Button() in 2 ways.
1. Using Mutable Interaction Source Parameter:
The Button() composable takes MutableInteractionSource as a parameter. So, we can use the second method.
@Composable
fun MyUI() {
Button(
onClick = {
// handle click events
},
interactionSource = NoRippleInteractionSource()
) {
Text(text = "Click")
}
}
class NoRippleInteractionSource : MutableInteractionSource {
override val interactions: Flow<Interaction> = emptyFlow()
override suspend fun emit(interaction: Interaction) {}
override fun tryEmit(interaction: Interaction) = true
}
Output:

2. Create a Button Using the Box:
We can also create a button using the Box and apply the first method.
@Composable
fun MyUI() {
val interactionSource = MutableInteractionSource()
Box(
modifier = Modifier
.size(width = 80.dp, height = 36.dp)
.background(
color = Color.Magenta,
shape = RoundedCornerShape(percent = 12)
)
.clickable(
interactionSource = interactionSource,
indication = null
) {
// handle click events
},
contentAlignment = Alignment.Center
) {
Text(
text = "Click Me",
color = Color.White
)
}
}
Output:

Related: Shapes in Jetpack Compose
These are the different ways to disable the ripple in Jetpack Compose. I hope you have learned something new. If you have any doubts, comment below.
Related:
Hello, thanks for the article, just want to tell you that Option 2 works also for Compose Buttons 🙂
How?
Using interactionSource = NoRippleInteractionSource() in the button Composable
?