@@ -10,6 +10,7 @@ import androidx.compose.runtime.remember
1010import androidx.compose.runtime.rememberCoroutineScope
1111import androidx.compose.runtime.rememberUpdatedState
1212import androidx.compose.ui.Modifier
13+ import androidx.compose.ui.geometry.Offset
1314import androidx.compose.ui.graphics.graphicsLayer
1415import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
1516import androidx.compose.ui.input.pointer.pointerInput
@@ -29,6 +30,7 @@ import androidx.compose.ui.unit.Constraints
2930import kotlinx.coroutines.launch
3031import kotlin.time.Duration
3132import kotlin.time.Duration.Companion.milliseconds
33+ import androidx.compose.ui.semantics.onLongClick as semanticsOnLongClick
3234
3335private val CLICK_DEBOUNCE = 500 .milliseconds
3436
@@ -69,41 +71,46 @@ fun Modifier.clickableAlpha(
6971 enabled : Boolean = true,
7072 ripple : Boolean = false,
7173 debounce : Duration = CLICK_DEBOUNCE ,
74+ onLongClick : (() -> Unit )? = null,
7275 onClick : (() -> Unit )? ,
7376): Modifier = when {
7477 onClick == null || ! enabled -> this
75- ripple ->
78+ ripple && onLongClick == null ->
7679 this
7780 .alphaFeedback(pressedAlpha)
7881 .clickable(onClick = rememberDebouncedClick(debounce, onClick))
7982
80- else -> this .then(ClickableAlphaElement (pressedAlpha, debounce, onClick))
83+ else -> this .then(ClickableAlphaElement (pressedAlpha, debounce, onLongClick, onClick))
8184}
8285
8386private data class ClickableAlphaElement (
8487 val pressedAlpha : Float ,
8588 val debounce : Duration ,
89+ val onLongClick : (() -> Unit )? ,
8690 val onClick : () -> Unit ,
8791) : ModifierNodeElement<ClickableAlphaNode>() {
88- override fun create (): ClickableAlphaNode = ClickableAlphaNode (pressedAlpha, debounce, onClick)
92+ override fun create (): ClickableAlphaNode = ClickableAlphaNode (pressedAlpha, debounce, onLongClick, onClick)
8993
9094 override fun update (node : ClickableAlphaNode ) {
9195 node.pressedAlpha = pressedAlpha
9296 node.debounce = debounce
97+ node.onLongClick = onLongClick
9398 node.onClick = onClick
9499 }
95100
96101 override fun InspectorInfo.inspectableProperties () {
97102 name = " clickableAlpha"
98103 properties[" pressedAlpha" ] = pressedAlpha
99104 properties[" debounce" ] = debounce
105+ properties[" onLongClick" ] = onLongClick
100106 properties[" onClick" ] = onClick
101107 }
102108}
103109
104110private class ClickableAlphaNode (
105111 var pressedAlpha : Float ,
106112 var debounce : Duration ,
113+ var onLongClick : (() -> Unit )? ,
107114 var onClick : () -> Unit ,
108115) : DelegatingNode(), LayoutModifierNode, SemanticsModifierNode {
109116
@@ -121,6 +128,7 @@ private class ClickableAlphaNode(
121128 coroutineScope.launch { animatable.animateTo(1f ) }
122129 }
123130 },
131+ onLongPress = if (onLongClick == null ) null else ::handleLongPress,
124132 onTap = {
125133 if (debouncer.tryClick(debounce, onClick)) {
126134 coroutineScope.launch {
@@ -136,6 +144,12 @@ private class ClickableAlphaNode(
136144 )
137145 }
138146
147+ @Suppress(" UNUSED_PARAMETER" )
148+ private fun handleLongPress (offset : Offset ) {
149+ onLongClick?.invoke()
150+ coroutineScope.launch { animatable.animateTo(1f ) }
151+ }
152+
139153 override fun MeasureScope.measure (measurable : Measurable , constraints : Constraints ): MeasureResult {
140154 val placeable = measurable.measure(constraints)
141155
@@ -152,6 +166,12 @@ private class ClickableAlphaNode(
152166 debouncer.tryClick(debounce, onClick)
153167 true
154168 }
169+ onLongClick?.let {
170+ semanticsOnLongClick {
171+ it()
172+ true
173+ }
174+ }
155175 }
156176}
157177
0 commit comments