Skip to content

Commit 9babb50

Browse files
committed
Interact with scrollbar only if drag direction matches scrollbar orientation
Change-Id: I8fb5a64098ea83458d25fd2b7363a6b5dd3fef2f
1 parent e13e84c commit 9babb50

File tree

1 file changed

+71
-33
lines changed
  • core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar

1 file changed

+71
-33
lines changed

core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/scrollbar/Scrollbar.kt

Lines changed: 71 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ package com.google.samples.apps.nowinandroid.core.designsystem.component.scrollb
1818

1919
import androidx.compose.animation.core.animateDpAsState
2020
import androidx.compose.foundation.gestures.Orientation
21+
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
2122
import androidx.compose.foundation.gestures.detectTapGestures
22-
import androidx.compose.foundation.gestures.draggable
23-
import androidx.compose.foundation.gestures.rememberDraggableState
23+
import androidx.compose.foundation.gestures.detectVerticalDragGestures
2424
import androidx.compose.foundation.hoverable
25+
import androidx.compose.foundation.interaction.DragInteraction
2526
import androidx.compose.foundation.interaction.MutableInteractionSource
2627
import androidx.compose.foundation.interaction.PressInteraction
2728
import androidx.compose.foundation.layout.Box
@@ -41,6 +42,7 @@ import androidx.compose.runtime.setValue
4142
import androidx.compose.ui.Alignment
4243
import androidx.compose.ui.Modifier
4344
import androidx.compose.ui.geometry.Offset
45+
import androidx.compose.ui.input.pointer.PointerInputChange
4446
import androidx.compose.ui.input.pointer.pointerInput
4547
import androidx.compose.ui.layout.onGloballyPositioned
4648
import androidx.compose.ui.layout.positionInRoot
@@ -53,7 +55,9 @@ import androidx.compose.ui.unit.max
5355
import androidx.compose.ui.util.packFloats
5456
import androidx.compose.ui.util.unpackFloat1
5557
import androidx.compose.ui.util.unpackFloat2
58+
import kotlinx.coroutines.TimeoutCancellationException
5659
import kotlinx.coroutines.delay
60+
import kotlinx.coroutines.withTimeout
5761
import kotlin.math.max
5862
import kotlin.math.min
5963

@@ -221,14 +225,6 @@ fun Scrollbar(
221225
a = track.size * thumbTravelPercent,
222226
b = track.size - thumbSizePx,
223227
)
224-
val draggableState = rememberDraggableState { delta ->
225-
if (draggedOffset == Offset.Unspecified) return@rememberDraggableState
226-
227-
draggedOffset = when (orientation) {
228-
Orientation.Vertical -> draggedOffset.copy(y = draggedOffset.y + delta)
229-
Orientation.Horizontal -> draggedOffset.copy(x = draggedOffset.x + delta)
230-
}
231-
}
232228

233229
// scrollbar track container
234230
Box(
@@ -251,36 +247,77 @@ fun Scrollbar(
251247
.pointerInput(Unit) {
252248
detectTapGestures(
253249
onPress = { offset ->
254-
val initialPress = PressInteraction.Press(offset)
255-
interactionSource?.tryEmit(initialPress)
256-
257-
// Start the press
258-
pressedOffset = offset
250+
try {
251+
// Wait for a long press before scrolling
252+
withTimeout(viewConfiguration.longPressTimeoutMillis) {
253+
tryAwaitRelease()
254+
}
255+
} catch (e: TimeoutCancellationException) {
256+
// Start the press triggered scroll
257+
val initialPress = PressInteraction.Press(offset)
258+
interactionSource?.tryEmit(initialPress)
259259

260-
interactionSource?.tryEmit(
261-
when {
262-
tryAwaitRelease() -> PressInteraction.Release(initialPress)
263-
else -> PressInteraction.Cancel(initialPress)
264-
},
265-
)
260+
pressedOffset = offset
261+
interactionSource?.tryEmit(
262+
when {
263+
tryAwaitRelease() -> PressInteraction.Release(initialPress)
264+
else -> PressInteraction.Cancel(initialPress)
265+
},
266+
)
266267

267-
// End the press
268-
pressedOffset = Offset.Unspecified
268+
// End the press
269+
pressedOffset = Offset.Unspecified
270+
}
269271
},
270272
)
271273
}
272274
// Process scrollbar drags
273-
.draggable(
274-
state = draggableState,
275-
orientation = orientation,
276-
interactionSource = interactionSource,
277-
onDragStarted = { startedPosition: Offset ->
278-
draggedOffset = startedPosition
279-
},
280-
onDragStopped = {
275+
.pointerInput(Unit) {
276+
var dragInteraction: DragInteraction.Start? = null
277+
val onDragStart: (Offset) -> Unit = { offset ->
278+
val start = DragInteraction.Start()
279+
dragInteraction = start
280+
interactionSource?.tryEmit(start)
281+
draggedOffset = offset
282+
}
283+
val onDragEnd: () -> Unit = {
284+
dragInteraction?.let { interactionSource?.tryEmit(DragInteraction.Stop(it)) }
285+
draggedOffset = Offset.Unspecified
286+
}
287+
val onDragCancel: () -> Unit = {
288+
dragInteraction?.let { interactionSource?.tryEmit(DragInteraction.Cancel(it)) }
281289
draggedOffset = Offset.Unspecified
282-
},
283-
),
290+
}
291+
val onDrag: (change: PointerInputChange, dragAmount: Float) -> Unit =
292+
onDrag@{ _, delta ->
293+
if (draggedOffset == Offset.Unspecified) return@onDrag
294+
draggedOffset = when (orientation) {
295+
Orientation.Vertical -> draggedOffset.copy(
296+
y = draggedOffset.y + delta,
297+
)
298+
299+
Orientation.Horizontal -> draggedOffset.copy(
300+
x = draggedOffset.x + delta,
301+
)
302+
}
303+
}
304+
305+
when (orientation) {
306+
Orientation.Horizontal -> detectHorizontalDragGestures(
307+
onDragStart = onDragStart,
308+
onDragEnd = onDragEnd,
309+
onDragCancel = onDragCancel,
310+
onHorizontalDrag = onDrag,
311+
)
312+
313+
Orientation.Vertical -> detectVerticalDragGestures(
314+
onDragStart = onDragStart,
315+
onDragEnd = onDragEnd,
316+
onDragCancel = onDragCancel,
317+
onVerticalDrag = onDrag,
318+
)
319+
}
320+
},
284321
) {
285322
val scrollbarThumbMovedDp = max(
286323
a = with(localDensity) { thumbMovedPx.toDp() },
@@ -338,6 +375,7 @@ fun Scrollbar(
338375
a = currentThumbMovedPercent + delta,
339376
b = destinationThumbMovedPercent,
340377
)
378+
341379
else -> max(
342380
a = currentThumbMovedPercent + delta,
343381
b = destinationThumbMovedPercent,

0 commit comments

Comments
 (0)