feat: predictive back handler

This commit is contained in:
LavaDesu 2025-04-29 15:01:28 +10:00
parent 1d27013c4d
commit a16487a9a7
Signed by: cilly
GPG key ID: 6500251E087653C9
3 changed files with 35 additions and 3 deletions

View file

@ -52,6 +52,7 @@ kotlin {
implementation(libs.moko.geo)
implementation(libs.moko.geo.compose)
implementation(projects.shared)
implementation(libs.ui.backhandler)
}
}

View file

@ -18,13 +18,16 @@ import androidx.compose.material3.rememberStandardBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.backhandler.PredictiveBackHandler
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import dev.icerock.moko.geo.compose.BindLocationTrackerEffect
@ -44,6 +47,7 @@ import moe.lava.banksia.resources.my_location_24
import moe.lava.banksia.ui.Searcher
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.ui.tooling.preview.Preview
import kotlin.coroutines.cancellation.CancellationException
import kotlin.math.roundToInt
fun buildBounds(points: List<Point>): Pair<Point, Point> {
@ -64,7 +68,7 @@ fun buildBounds(points: List<Point>): Pair<Point, Point> {
return Pair(Point(north, east), Point(south, west))
}
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
@Preview
fun App() {
@ -138,12 +142,17 @@ fun App() {
newCameraPosition = Pair(Point(0.0, 0.0), bounds)
}
var sheetSwipeEnabled by remember { mutableStateOf(true) }
var peekHeight by remember { mutableStateOf(128.dp) }
var peekHeightMultiplier by remember { mutableFloatStateOf(1F) }
MaterialTheme {
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetPeekHeight = 250.dp,
sheetPeekHeight = peekHeight * peekHeightMultiplier,
modifier = Modifier.fillMaxSize(),
sheetContent = { Box(modifier = Modifier) },
sheetSwipeEnabled = sheetSwipeEnabled,
) {
Maps(
modifier = Modifier.fillMaxSize(),
@ -161,6 +170,27 @@ fun App() {
onRouteChange = { route = it }
)
PredictiveBackHandler(scaffoldState.bottomSheetState.currentValue != SheetValue.Hidden) { progress ->
sheetSwipeEnabled = false
try {
progress.collect { backEvent ->
if (scaffoldState.bottomSheetState.currentValue == SheetValue.PartiallyExpanded) {
peekHeightMultiplier = 1F - backEvent.progress
}
}
if (scaffoldState.bottomSheetState.currentValue == SheetValue.Expanded)
scope.launch { scaffoldState.bottomSheetState.partialExpand() }
else if (scaffoldState.bottomSheetState.currentValue == SheetValue.PartiallyExpanded)
scope.launch {
scaffoldState.bottomSheetState.hide()
peekHeightMultiplier = 1F
}
} catch (_: CancellationException) {
peekHeightMultiplier = 1F
}
sheetSwipeEnabled = true
}
Box(
Modifier.windowInsetsPadding(WindowInsets.safeContent.add(WindowInsets(bottom = extInsets))),
contentAlignment = Alignment.BottomEnd

View file

@ -11,7 +11,7 @@ androidx-espresso-core = "3.6.1"
androidx-lifecycle = "2.8.4"
androidx-material = "1.12.0"
androidx-test-junit = "1.2.1"
compose-multiplatform = "1.7.3"
compose-multiplatform = "1.8.0-beta02"
coroutines = "1.9.0"
geo = "0.8.0"
junit = "4.13.2"
@ -57,6 +57,7 @@ okio = { module = "com.squareup.okio:okio", version.ref = "okio" }
play-services-location = { module = "com.google.android.gms:play-services-location", version.ref = "playServicesLocation" }
play-services-maps = { module = "com.google.android.gms:play-services-maps", version.ref = "playServicesMaps" }
secrets-gradle-plugin = { module = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin", version.ref = "secretsGradlePlugin" }
ui-backhandler = { module = "org.jetbrains.compose.ui:ui-backhandler", version.ref = "compose-multiplatform" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }