0

I have seen that we can disable the ripple effect of a view with the clickable(interactionSource, indication) inside for example a row or column but my question is that if we can disable it from a Button or FloatingActionButton

I see that FloatingActionButton has an interactionSource attribute and I have tried this

FloatingActionButton(
        modifier = Modifier
            .size(40.dp),
        onClick = {
            buttonState = when (buttonState) {
                ButtonState.PRESSED -> ButtonState.UNPRESSED
                ButtonState.UNPRESSED -> ButtonState.PRESSED
            }
        },
        interactionSource = remember {
            MutableInteractionSource()
        })

this is not working to disable the ripple effect.

Then I have tried with the indication modifier like this

FloatingActionButton(
        modifier = Modifier
            .size(40.dp)
            .indication(
                interactionSource = remember {
                    MutableInteractionSource()
                },
                indication = null
            ),
        onClick = {
            buttonState = when (buttonState) {
                ButtonState.PRESSED -> ButtonState.UNPRESSED
                ButtonState.UNPRESSED -> ButtonState.PRESSED
            }
        })

also is not working, and then last thing I tried is adding the .clickable(...) in the modifier of the Fab button but I think that is pointless since the button has its own onClick event.

All the cases above yields to this

enter image description here

Is there anyway from any Button to disable its ripple effect without adding a Column or Box with a clickable attribute into its modifier ?

Gastón Saillén
  • 12,319
  • 5
  • 67
  • 77

2 Answers2

5

You can change ripple o by providing RippleTheme

private class CustomRippleTheme : RippleTheme {
    @Composable
    override fun defaultColor(): Color = Color.Unspecified

    @Composable
    override fun rippleAlpha(): RippleAlpha = RippleAlpha(
        draggedAlpha = 0f,
        focusedAlpha = 0f,
        hoveredAlpha = 0f,
        pressedAlpha = 0f,
    )
}

Demo

@Composable
private fun RippleDemo() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(50.dp)
    ) {

        Button(onClick = { /*TODO*/ }) {
            Text("Button with ripple", fontSize = 20.sp)
        }

        Spacer(Modifier.height(20.dp))

        FloatingActionButton(onClick = { /*TODO*/ }) {
            Icon(imageVector = Icons.Filled.Add, contentDescription = null)
        }
        Spacer(Modifier.height(20.dp))
        CompositionLocalProvider(LocalRippleTheme provides CustomRippleTheme()) {
            Button(onClick = { /*TODO*/ }) {
                Text("Button with No ripple", fontSize = 20.sp)
            }
            Spacer(Modifier.height(20.dp))

            FloatingActionButton(onClick = { /*TODO*/ }) {
                Icon(imageVector = Icons.Filled.Add, contentDescription = null)
            }
        }
    }
}

Result

enter image description here

Thracian
  • 43,021
  • 16
  • 133
  • 222
  • Answer from Richard Onslow Roper is also true. When you want to modify something internal you can just copy code and update it. Most of the Composbles code is pretty straightforward. – Thracian Aug 25 '22 at 17:11
2

A Button, internally, is just a surface with modifications applied to it to make it clickable. It has a default indication set within the implementation, hence cannot be "turned off" at the calling site.

Just pull up the source code and remove the indication, storing the resultant inside a new Composable.

Just do a quick Ctrl+Left Click on the text "Button" in Studio, and it'll take you there.

Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42
  • hmm I'm not looking into overriding an inplementation just for disabling a ripple effect on a button, will be easier to just create a rounded surface with a clickable attribute – Gastón Saillén Aug 25 '22 at 15:29
  • It's not an implementation override, per se. al you are doing is copying an implementation, and creating a new Composable with it, which you can use. If you want, you can just add a parameter called `showRipple`, and it'll work as you want, both as the default implementation, and as a custom Composable. And yes, it wouldn't make sense to not have ripple on a regular button which is why it is defaulted up. – Richard Onslow Roper Aug 25 '22 at 15:56
  • I meant that there should be a way inside of the current implementation of button of doing it , trying to go the easiest way – Gastón Saillén Aug 25 '22 at 16:05
  • If there was an easier way, I would have lead with that. See [this video](https://youtu.be/DDd6IOlH3io?t=513)' – Richard Onslow Roper Aug 25 '22 at 16:07
  • yes, but the purpose of the question is to know if there is any posible way of not leading to the creation of a custom button for my use case and use what FAB offers (that is enough for what I need) – Gastón Saillén Aug 25 '22 at 16:12
  • Sir, no matter what modifiers, or forces you apply on this composable externally, but when it reaches the internal execution, it sees there's an indication being applied to the surface, and so it renders it. There's a harcoded ripple inside the implementation with no conditions applied on it. It is completely illogical to try to "find" a way to disable it. It's like trying to read what modifier was passed in as a parameter, from inside the composable. It is blocked, and is done for a reason. I completely understand your question, and you have gained the answer. Further discussion is futile. – Richard Onslow Roper Aug 25 '22 at 16:15
  • ok I will go with that, thanks for the answer – Gastón Saillén Aug 25 '22 at 16:22