I’m trying to figure out how to replicate some of ...
# compose
e
I’m trying to figure out how to replicate some of the old drawable state list background color functionality, where the background color changed on press (with no ripple), and really struggling. any resources on how to accomplish this?
z
What exactly are you trying to do? Implement ripple from scratch? Add a touch ripple to a custom component?
e
i just want to replicate the old state list behavior. if button is pressed, button background color is blue, otherwise it’s teal. no ripple at all.
c
Can't you just switch on state and change the color accordingly?
Like background = if (PRESSED) Color.Blue else Color.Red
e
i’d be happy to do that but the initial Material button colors implementation doesn’t account for any interaction state, only enabled
Copy code
@Stable
interface ButtonColors {
    /**
     * Represents the background color for this button, depending on [enabled].
     *
     * @param enabled whether the button is enabled
     */
    @Composable
    fun backgroundColor(enabled: Boolean): State<Color>

    /**
     * Represents the content color for this button, depending on [enabled].
     *
     * @param enabled whether the button is enabled
     */
    @Composable
    fun contentColor(enabled: Boolean): State<Color>
}
and i’m not sure how to make an impl of this interface respect the interactionSource to get that PRESSED info in and updated
i tried defining this custom ButtonColor impl:
Copy code
private class OurButtonColors(val pressed: State<Boolean>) : ButtonColors {
    @Composable
    override fun backgroundColor(enabled: Boolean): State<Color> {
        return if (pressed.value) {
            rememberUpdatedState(newValue = Color.Red)
        } else {
            rememberUpdatedState(newValue = Color.Magenta)
        }
    }

    @Composable
    override fun contentColor(enabled: Boolean): State<Color> {
        return rememberUpdatedState(newValue = Color.Green)
    }

}
and passed it `
Copy code
val isPressed = interactionSource.collectIsPressedAsState()
`
but that doesn’t change to red on press, and i’m kind of confused
c
I'm assuming material buttons probably adhere to material ripple spec, etc. But you should be able to copy paste that implementation and make whatever changes you need for your custom design system or just use the regular button.
I'm also new to Compose so don't listen to me. But from what I gather... That's basically what you would do. Maybe @Louis Pullen-Freilich [G] would know better. But I think the idea of color state lists as you said doesn't really exist. Use state and you do whatever you want based on it.
z
l
i just want to replicate the old state list behavior. if button is pressed, button background color is blue, otherwise it’s teal. no ripple at all.
At this point it is probably easier just to build your own button, since ripple is a core part of Material components. Then you can just do:
Copy code
val isPressed = interactionSource.collectIsPressedAsState()

val backgroundColor = if (isPressed) .. else ..

Surface(backgroundColor...)
1
z
not to be pedantic, but ripple isn’t really a core part of material, it’s actually in its own dedicated library for compose: https://developer.android.com/reference/kotlin/androidx/compose/material/ripple/package-summary
l
Well, it’s a bit tricky - on Android in particular the line between Material design and the platform is a bit blurry. A ripple is explicitly Material design, but at the same time since Android devices and applications use ripples, even non-Material applications typically use ripples so the behaviour and feel is consistent with other applications on the device, similar to how the fling curve is constant. We moved ripple into its own module to make it easy for non-Material design applications to use it, without needing to bring in all of Material, but within Material every component uses a ripple and since this is explicitly part of the component’s spec, it’s not something that can be changed and replaced with something else.
👍 1
e
I figured out that my issue was simply that I wasn’t connecting my interactionSource to the button with
interactionSource = interactionSource,
in the Composable call