Improve pager gesture handling (again)

This commit is contained in:
MM20 2023-07-12 17:41:04 +02:00
parent d1218e8d2e
commit 3759a99510
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389

View File

@ -667,9 +667,10 @@ fun Modifier.pagerScaffoldScrollHandler(
awaitEachGesture { awaitEachGesture {
var overSlop = false var overSlop = false
var lockedInScroll = disablePager val initialDown =
val initialDown = awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial) awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
val down = if (scrollableState.isScrollInProgress || pagerState.isScrollInProgress) { val down =
if (scrollableState.isScrollInProgress || pagerState.isScrollInProgress) {
overSlop = true overSlop = true
scope.launch { scope.launch {
scrollableState.scrollBy(0f) scrollableState.scrollBy(0f)
@ -681,23 +682,19 @@ fun Modifier.pagerScaffoldScrollHandler(
} }
velocityTracker.resetTracking() velocityTracker.resetTracking()
velocityTracker.addPointerInputChange(down) velocityTracker.addPointerInputChange(down)
val notCanceled = drag(down.id) { val canceled = !drag(down.id) {
if (it.isConsumed) return@drag if (it.isConsumed) return@drag
val totalDrag = down.position - it.position val totalDrag = down.position - it.position
if (!lockedInScroll && totalDrag.y.absoluteValue > lockScrollThreshold) { if (!overSlop && totalDrag.getDistanceSquared() > touchSlopSq) {
lockedInScroll = true
scope.launch {
pagerState.animateScrollToPage(pagerState.settledPage)
}
}
if (!lockedInScroll && !overSlop && totalDrag.getDistanceSquared() > touchSlopSq) {
overSlop = true overSlop = true
} }
if (!overSlop) return@drag if (!overSlop) return@drag
val dragAmount = it val dragAmount = it
.positionChange() .positionChange()
.let { .let {
if (!overSlop || lockedInScroll) it.copy(x = 0f) else it if (it.x.absoluteValue > it.y.absoluteValue) it.copy(y = 0f) else it.copy(
x = 0f
)
} }
it.consume() it.consume()
velocityTracker.addPointerInputChange(it) velocityTracker.addPointerInputChange(it)
@ -707,11 +704,11 @@ fun Modifier.pagerScaffoldScrollHandler(
NestedScrollSource.Drag NestedScrollSource.Drag
) )
val available = dragAmount - preConsumed val available = dragAmount - preConsumed
val consumedY = scrollableState.scrollBy(available.y * scrollMultiplier) * scrollMultiplier val consumedY =
val consumedX = if (!lockedInScroll) { scrollableState.scrollBy(available.y * scrollMultiplier) * scrollMultiplier
pagerState.scrollBy(available.x * pagerMultiplier) * pagerMultiplier val consumedX = pagerState.scrollBy(available.x * pagerMultiplier) * -1f
} else available.x val totalConsumed =
val totalConsumed = Offset(preConsumed.x + consumedX, preConsumed.y + consumedY) Offset(preConsumed.x + consumedX, preConsumed.y + consumedY)
nestedScrollDispatcher.dispatchPostScroll( nestedScrollDispatcher.dispatchPostScroll(
totalConsumed, totalConsumed,
dragAmount - totalConsumed, dragAmount - totalConsumed,
@ -719,11 +716,10 @@ fun Modifier.pagerScaffoldScrollHandler(
) )
} }
} }
if (notCanceled) {
val velocity = velocityTracker val velocity = velocityTracker
.calculateVelocity() .calculateVelocity()
if (velocity.x.absoluteValue > velocity.y.absoluteValue && !lockedInScroll) { if (canceled || velocity.x.absoluteValue > velocity.y.absoluteValue) {
scope.launch { scope.launch {
val preConsumed = nestedScrollDispatcher.dispatchPreFling(velocity) val preConsumed = nestedScrollDispatcher.dispatchPreFling(velocity)
val flingVelocity = (velocity - preConsumed).x val flingVelocity = (velocity - preConsumed).x
@ -751,7 +747,8 @@ fun Modifier.pagerScaffoldScrollHandler(
launch { launch {
with(flingBehavior) { with(flingBehavior) {
scrollableState.scroll { scrollableState.scroll {
consumed = performFling(flingVelocity * scrollMultiplier) * scrollMultiplier consumed =
performFling(flingVelocity * scrollMultiplier) * scrollMultiplier
} }
} }
val totalConsumed = val totalConsumed =
@ -768,7 +765,6 @@ fun Modifier.pagerScaffoldScrollHandler(
} }
} }
} }
}
} }
internal object DefaultNestedScrollConnection : NestedScrollConnection {} internal object DefaultNestedScrollConnection : NestedScrollConnection {}