M3 ModalBottomSheet swipe to dismiss fix.
In the M3 AnchoredDraggable migration of ModalBottomSheet one custom implementation of draggable was removed in favor of anchoredDraggable. This generated a bug where swipe to dismiss actions were not calling onDismissRequest after hiding the sheet.
Test: Added tests to verify the new behavior.
Fixes: 298648794
Relnote: Fixed a bug where ModalBottomSheet was not calling onDismissedRequest when dismissing it by swiping down on the sheet.
Change-Id: Idfdd8b490caed6486292ae244ba9e4e9fb813f96
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
index 85a2ddc..6d2d0b7 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
@@ -144,6 +144,42 @@
}
@Test
+ fun modalBottomSheet_isDismissedOnSwipeDown() {
+ var showBottomSheet by mutableStateOf(true)
+ val sheetState = SheetState(skipPartiallyExpanded = false, density = rule.density)
+
+ rule.setContent {
+ val windowInsets = if (edgeToEdgeWrapper.edgeToEdgeEnabled)
+ WindowInsets(0) else BottomSheetDefaults.windowInsets
+
+ if (showBottomSheet) {
+ ModalBottomSheet(
+ sheetState = sheetState,
+ onDismissRequest = { showBottomSheet = false },
+ windowInsets = windowInsets
+ ) {
+ Box(
+ Modifier
+ .size(sheetHeight)
+ .testTag(sheetTag)
+ )
+ }
+ }
+ }
+
+ assertThat(sheetState.isVisible).isTrue()
+
+ // Swipe Down
+ rule.onNodeWithTag(sheetTag).performTouchInput {
+ swipeDown()
+ }
+ rule.waitForIdle()
+
+ // Bottom sheet should not exist
+ rule.onNodeWithTag(sheetTag).assertDoesNotExist()
+ }
+
+ @Test
fun modalBottomSheet_fillsScreenWidth() {
var boxWidth = 0
var screenWidth by mutableStateOf(0)
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt
index 85e41b3..771d739 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt
@@ -28,6 +28,7 @@
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
@@ -198,10 +199,12 @@
)
}
)
- .anchoredDraggable(
- state = sheetState.anchoredDraggableState,
+ .draggable(
+ state = sheetState.anchoredDraggableState.draggableState,
orientation = Orientation.Vertical,
- enabled = sheetState.isVisible
+ enabled = sheetState.isVisible,
+ startDragImmediately = sheetState.anchoredDraggableState.isAnimationRunning,
+ onDragStopped = { settleToDismiss(it) }
)
.modalBottomSheetAnchors(
sheetState = sheetState,