Skip to content

Commit fb3d442

Browse files
authored
library: fix bottom sheet nested scroll dismissal (#340)
* library: fix bottom sheet nested scroll dismissal - Fix bottom sheet dismissal so scrollable content only drags the sheet when the gesture starts at the top. * fix(ui): ensure nested scroll gesture reset in BottomSheet
1 parent 5985fa7 commit fb3d442

1 file changed

Lines changed: 36 additions & 14 deletions

File tree

miuix-ui/src/commonMain/kotlin/top/yukonga/miuix/kmp/layout/BottomSheetContentLayout.kt

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ import top.yukonga.miuix.kmp.squircle.squircleSurface
8484
import top.yukonga.miuix.kmp.theme.LocalDismissState
8585
import top.yukonga.miuix.kmp.theme.MiuixTheme
8686
import kotlin.coroutines.cancellation.CancellationException
87+
import kotlin.math.abs
8788

8889
/**
8990
* Internal shared layout logic for [OverlayBottomSheet] and [WindowBottomSheet].
@@ -440,11 +441,19 @@ internal fun BottomSheetContent(
440441
}
441442
}
442443

444+
val isNestedScrollGestureStarted = remember { mutableStateOf(false) }
445+
val canDragSheetFromNestedScroll = remember { mutableStateOf(false) }
446+
447+
fun resetNestedScrollGesture() {
448+
isNestedScrollGestureStarted.value = false
449+
canDragSheetFromNestedScroll.value = false
450+
}
451+
443452
// Nested scroll logic
444453
val nestedScrollConnection = remember(enableNestedScroll, allowDismiss, density) {
445454
object : NestedScrollConnection {
446455
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
447-
if (!enableNestedScroll) return Offset.Zero
456+
if (!enableNestedScroll || source != NestedScrollSource.UserInput) return Offset.Zero
448457

449458
// Allow interruption whenever settling
450459
if (isSettling.value) {
@@ -467,10 +476,15 @@ internal fun BottomSheetContent(
467476
}
468477

469478
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
470-
if (!enableNestedScroll) return Offset.Zero
479+
if (!enableNestedScroll || source != NestedScrollSource.UserInput) return Offset.Zero
471480

472481
val delta = available.y
473-
if (delta > 0) {
482+
if (!isNestedScrollGestureStarted.value) {
483+
isNestedScrollGestureStarted.value = true
484+
canDragSheetFromNestedScroll.value = delta > 0 && abs(consumed.y) < 0.5f
485+
}
486+
487+
if (delta > 0 && canDragSheetFromNestedScroll.value) {
474488
if (!allowDismiss) return Offset.Zero
475489

476490
if (isSettling.value) {
@@ -495,24 +509,32 @@ internal fun BottomSheetContent(
495509
}
496510

497511
override suspend fun onPreFling(available: Velocity): Velocity {
498-
if (!enableNestedScroll || isSettling.value) return Velocity.Zero
512+
try {
513+
if (!enableNestedScroll || isSettling.value) return Velocity.Zero
499514

500-
// Take over fling if the sheet is offset
501-
if (dragOffsetY.value > 0) {
502-
performSettle(available.y)
503-
return available
515+
// Take over fling if the sheet is offset.
516+
if (dragOffsetY.value > 0) {
517+
performSettle(available.y)
518+
return available
519+
}
520+
return Velocity.Zero
521+
} finally {
522+
resetNestedScrollGesture()
504523
}
505-
return Velocity.Zero
506524
}
507525

508526
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
509-
if (!enableNestedScroll || isSettling.value) return Velocity.Zero
527+
try {
528+
if (!enableNestedScroll || isSettling.value) return Velocity.Zero
510529

511-
if (dragOffsetY.value > 0) {
512-
performSettle(available.y)
513-
return available
530+
if (dragOffsetY.value > 0) {
531+
performSettle(available.y)
532+
return available
533+
}
534+
return super.onPostFling(consumed, available)
535+
} finally {
536+
resetNestedScrollGesture()
514537
}
515-
return super.onPostFling(consumed, available)
516538
}
517539
}
518540
}

0 commit comments

Comments
 (0)