Skip to content

Commit

Permalink
Introduce confirmDetentChange() callback on Sheets
Browse files Browse the repository at this point in the history
Fixes: #45
  • Loading branch information
alexstyl committed Dec 1, 2024
1 parent 1b622e0 commit 1048ee6
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 22 deletions.
19 changes: 13 additions & 6 deletions core/src/commonMain/kotlin/BottomSheet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ private fun Saver(
velocityThreshold: () -> Float,
positionalThreshold: (totalDistance: Float) -> Float,
decayAnimationSpec: DecayAnimationSpec<Float>,
confirmDetentChange: (SheetDetent) -> Boolean,
): Saver<BottomSheetState, *> = mapSaver(save = { mapOf("detent" to it.currentDetent.identifier) }, restore = { map ->
val selectedDetentName = map["detent"]
BottomSheetState(
Expand All @@ -50,6 +51,7 @@ private fun Saver(
velocityThreshold = velocityThreshold,
positionalThreshold = positionalThreshold,
decayAnimationSpec = decayAnimationSpec,
confirmDetentChange = confirmDetentChange,
)
})

Expand All @@ -58,9 +60,10 @@ public fun rememberBottomSheetState(
initialDetent: SheetDetent,
detents: List<SheetDetent> = listOf(SheetDetent.Hidden, SheetDetent.FullyExpanded),
animationSpec: AnimationSpec<Float> = tween(),
confirmDetentChange: (SheetDetent) -> Boolean = { true },
decayAnimationSpec: DecayAnimationSpec<Float> = rememberSplineBasedDecay(),
velocityThreshold: () -> Dp = { 125.dp },
positionalThreshold: (totalDistance: Dp) -> Dp = { 56.dp }
positionalThreshold: (totalDistance: Dp) -> Dp = { 56.dp },
): BottomSheetState {
val density = LocalDensity.current
val scope = rememberCoroutineScope()
Expand All @@ -79,7 +82,8 @@ public fun rememberBottomSheetState(
positionalThreshold(totalDistance.toDp()).toPx()
}
},
decayAnimationSpec = decayAnimationSpec
decayAnimationSpec = decayAnimationSpec,
confirmDetentChange = confirmDetentChange,
)
) {
BottomSheetState(
Expand All @@ -97,7 +101,8 @@ public fun rememberBottomSheetState(
positionalThreshold(totalDistance.toDp()).toPx()
}
},
decayAnimationSpec = decayAnimationSpec
decayAnimationSpec = decayAnimationSpec,
confirmDetentChange = confirmDetentChange
)
}
}
Expand Down Expand Up @@ -134,7 +139,8 @@ public class BottomSheetState internal constructor(
animationSpec: AnimationSpec<Float>,
velocityThreshold: () -> Float,
positionalThreshold: (totalDistance: Float) -> Float,
decayAnimationSpec: DecayAnimationSpec<Float>
decayAnimationSpec: DecayAnimationSpec<Float>,
internal val confirmDetentChange: (SheetDetent) -> Boolean,
) {
init {
check(detents.isNotEmpty()) {
Expand Down Expand Up @@ -163,6 +169,7 @@ public class BottomSheetState internal constructor(
velocityThreshold = velocityThreshold,
snapAnimationSpec = animationSpec,
decayAnimationSpec = decayAnimationSpec,
confirmValueChange = confirmDetentChange,
)

public var currentDetent: SheetDetent
Expand All @@ -180,7 +187,7 @@ public class BottomSheetState internal constructor(
get() = anchoredDraggableState.targetValue

public val isIdle: Boolean by derivedStateOf {
progress == 1f && currentDetent == targetDetent && anchoredDraggableState.isAnimationRunning.not()
(offset == 1f || offset == 0f) && currentDetent == targetDetent && anchoredDraggableState.isAnimationRunning.not()
}

public val progress: Float
Expand Down Expand Up @@ -227,7 +234,7 @@ public fun BottomSheet(
state: BottomSheetState,
modifier: Modifier = Modifier,
enabled: Boolean = true,
content: @Composable BottomSheetScope.() -> Unit,
content: @Composable (BottomSheetScope.() -> Unit),
) {
val scope = remember { BottomSheetScope(state, enabled) }
scope.enabled = enabled
Expand Down
43 changes: 27 additions & 16 deletions core/src/commonMain/kotlin/ModalBottomSheet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,42 @@ public fun rememberModalBottomSheetState(
animationSpec: AnimationSpec<Float> = tween(),
velocityThreshold: () -> Dp = { 125.dp },
positionalThreshold: (totalDistance: Dp) -> Dp = { 56.dp },
confirmDetentChange: (SheetDetent) -> Boolean = { true },
decayAnimationSpec: DecayAnimationSpec<Float> = rememberSplineBasedDecay()
): ModalBottomSheetState {
val actualDetents = (setOf(SheetDetent.Hidden) + detents).toList()
val sheetState = rememberBottomSheetState(
initialDetent = SheetDetent.Hidden,
detents = actualDetents,
initialDetent = initialDetent,
detents = detents,
animationSpec = animationSpec,
velocityThreshold = velocityThreshold,
positionalThreshold = positionalThreshold,
decayAnimationSpec = decayAnimationSpec,
confirmDetentChange = confirmDetentChange,
)
return rememberSaveable(
saver = mapSaver(
save = { modalBottomSheetState -> mapOf("detent" to modalBottomSheetState.currentDetent.identifier) },
restore = { map ->
val restoredDetent = actualDetents.first { it.identifier == map["detent"] }
val restoredDetent = detents.first { it.identifier == map["detent"] }
ModalBottomSheetState(
bottomSheetDetent = restoredDetent,
sheetState = sheetState
bottomSheetState = sheetState
)
}
)
) {
ModalBottomSheetState(
bottomSheetDetent = initialDetent,
sheetState = sheetState
)
}
),
init = {
ModalBottomSheetState(
bottomSheetDetent = initialDetent,
bottomSheetState = sheetState
)
}
)
}

public class ModalBottomSheetState internal constructor(
internal val bottomSheetDetent: SheetDetent,
sheetState: BottomSheetState
internal val bottomSheetState: BottomSheetState
) {
internal val bottomSheetState by mutableStateOf<BottomSheetState>(sheetState)

internal var modalDetent by mutableStateOf(bottomSheetDetent)

Expand Down Expand Up @@ -154,7 +155,11 @@ public fun ModalBottomSheet(
if (scope.visibleState.currentState || scope.visibleState.targetState || scope.visibleState.isIdle.not()) {
val onKeyEvent = if (properties.dismissOnBackPress) {
{ event: KeyEvent ->
if (event.type == KeyEventType.KeyDown && (event.key == Key.Back || event.key == Key.Escape)) {
if (
event.type == KeyEventType.KeyDown
&& (event.key == Key.Back || event.key == Key.Escape)
&& state.bottomSheetState.confirmDetentChange(SheetDetent.Hidden)
) {
scope.sheetState.currentDetent = SheetDetent.Hidden
true
} else false
Expand All @@ -168,7 +173,13 @@ public fun ModalBottomSheet(
.fillMaxSize()
.let {
if (properties.dismissOnClickOutside) {
it.pointerInput(Unit) { detectTapGestures { state.currentDetent = SheetDetent.Hidden } }
it.pointerInput(Unit) {
detectTapGestures {
if (state.bottomSheetState.confirmDetentChange(SheetDetent.Hidden)) {
state.currentDetent = SheetDetent.Hidden
}
}
}
} else it
}
) {
Expand Down

0 comments on commit 1048ee6

Please sign in to comment.