androidx.compose.material3.ripple
Interfaces
RippleNodeConfiguration.DragConfiguration |
Represents the configuration for the visual representation of drag |
Cmn
|
RippleNodeConfiguration.FocusConfiguration |
Represents the configuration for the visual representation of focus |
Cmn
|
RippleNodeConfiguration.HoverConfiguration |
Represents the configuration for the visual representation of hover |
Cmn
|
RippleNodeConfiguration.PressConfiguration |
Represents the configuration for the visual representation of a press |
Cmn
|
Classes
RippleNodeConfiguration |
The configuration for the ripple node created by |
Cmn
|
RippleNodeConfiguration.DragConfiguration.Opacity |
An opacity-based drag visual. |
Cmn
|
RippleNodeConfiguration.FocusConfiguration.InsetRing |
An inset ring focus visual - the created ripple will show an inset focus ring. |
Cmn
|
RippleNodeConfiguration.FocusConfiguration.Opacity |
An opacity-based focus visual. |
Cmn
|
RippleNodeConfiguration.HoverConfiguration.Opacity |
An opacity-based hover visual. |
Cmn
|
RippleNodeConfiguration.PressConfiguration.Opacity |
An opacity-based press visual - the created ripple will show a layer with the given |
Cmn
|
Objects
RippleNodeConfiguration.DragConfiguration.None |
No drag visual - the created ripple will not show anything for drag. |
Cmn
|
RippleNodeConfiguration.FocusConfiguration.None |
No focus visual - the created ripple will not show anything for focus. |
Cmn
|
RippleNodeConfiguration.HoverConfiguration.None |
No hover visual - the created ripple will not show anything for hover. |
Cmn
|
RippleNodeConfiguration.PressConfiguration.None |
No press visual - the created ripple will not show anything for press. |
Cmn
|
Top-level functions summary
DelegatableNode |
createRippleModifierNode(Creates a Ripple node using the values provided. |
Cmn
|
Top-level functions
createRippleModifierNode
fun createRippleModifierNode(
interactionSource: InteractionSource,
rippleNodeConfiguration: () -> RippleNodeConfiguration
): DelegatableNode
Creates a Ripple node using the values provided.
A Ripple is a Material 3 node that expresses different Interactions by drawing ripple animations, and state layers, and other graphical effects.
A Ripple responds to PressInteraction.Press by starting a new RippleAnimation, and responds to other Interactions by showing a fixed state layer with varying alpha values depending on the Interaction, or an inset ring for FocusInteraction, depending on the supplied RippleNodeConfiguration.
This Ripple node is a low level building block for building IndicationNodeFactory implementations that use a Ripple - higher level design system libraries such as material3 provide ripple implementations using this node internally. In most cases you should use those factories directly: this node exists for design system libraries to delegate their Ripple implementation to, after querying any required theme values for customizing the Ripple.
NOTE: when using this factory with DelegatingNode.delegate, ensure that the node is created once or DelegatingNode.undelegate is called in Modifier.Node.onDetach. Repeatedly delegating to a new node returned by this method in Modifier.Node.onAttach without removing the old one will result in multiple ripple nodes being attached to the node.
import androidx.compose.foundation.IndicationNodeFactory import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.InteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size import androidx.compose.material3.ripple.RippleNodeConfiguration import androidx.compose.material3.ripple.createRippleModifierNode import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorProducer import androidx.compose.ui.graphics.isSpecified import androidx.compose.ui.node.CompositionLocalConsumerModifierNode import androidx.compose.ui.node.DelegatableNode import androidx.compose.ui.node.DelegatingNode import androidx.compose.ui.node.ObserverModifierNode import androidx.compose.ui.node.currentValueOf import androidx.compose.ui.node.observeReads import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp /** Example CompositionLocals for a custom design system theme. */ val LocalCustomRippleColor: ProvidableCompositionLocal<Color> = compositionLocalOf { Color.Red } val LocalCustomRippleEnabled: ProvidableCompositionLocal<Boolean> = compositionLocalOf { true } /** * A custom [Modifier.Node] that queries design system theme values and delegates to * [createRippleModifierNode]. */ class CustomRippleNode( private val interactionSource: InteractionSource, private val bounded: Boolean, private val radius: Dp, private val color: Color, ) : DelegatingNode(), CompositionLocalConsumerModifierNode, ObserverModifierNode { private var rippleNode: DelegatableNode? = null private val calculateColor = ColorProducer { if (color.isSpecified) { color } else { currentValueOf(LocalCustomRippleColor) } } private val rippleNodeConfiguration = RippleNodeConfiguration( isBounded = bounded, radius = radius, color = calculateColor, pressConfiguration = RippleNodeConfiguration.PressConfiguration.Opacity(alpha = 0.24f), focusConfiguration = RippleNodeConfiguration.FocusConfiguration.Opacity(alpha = 0.24f), hoverConfiguration = RippleNodeConfiguration.HoverConfiguration.Opacity(alpha = 0.08f), dragConfiguration = RippleNodeConfiguration.DragConfiguration.Opacity(alpha = 0.16f), ) override fun onAttach() { updateConfiguration() } override fun onObservedReadsChanged() { updateConfiguration() } private fun updateConfiguration() { observeReads { val isEnabled = currentValueOf(LocalCustomRippleEnabled) if (isEnabled) { if (rippleNode == null) { attachNewRipple() } } else { removeRipple() } } } private fun attachNewRipple() { rippleNode = delegate( createRippleModifierNode( interactionSource = interactionSource, rippleNodeConfiguration = { rippleNodeConfiguration }, ) ) } private fun removeRipple() { rippleNode?.let { undelegate(it) } rippleNode = null } } /** A custom [IndicationNodeFactory] that creates a [CustomRippleNode]. */ class CustomRipple( private val bounded: Boolean = true, private val radius: Dp = Dp.Unspecified, private val color: Color = Color.Unspecified, ) : IndicationNodeFactory { override fun create(interactionSource: InteractionSource): DelegatableNode { return CustomRippleNode(interactionSource, bounded, radius, color) } override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is CustomRipple) return false if (bounded != other.bounded) return false if (radius != other.radius) return false if (color != other.color) return false return true } override fun hashCode(): Int { var result = bounded.hashCode() result = 31 * result + radius.hashCode() result = 31 * result + color.hashCode() return result } } val interactionSource = remember { MutableInteractionSource() } Box( modifier = Modifier.size(100.dp) .clickable( interactionSource = interactionSource, indication = CustomRipple(color = Color.Blue), onClick = {}, ) )
| Parameters | |
|---|---|
interactionSource: InteractionSource |
the |
rippleNodeConfiguration: () -> RippleNodeConfiguration |
the |
| Returns | |
|---|---|
DelegatableNode |
a |