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)
implementation(libs.moko.geo.compose) implementation(libs.moko.geo.compose)
implementation(projects.shared) 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.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.backhandler.PredictiveBackHandler
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import dev.icerock.moko.geo.compose.BindLocationTrackerEffect 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 moe.lava.banksia.ui.Searcher
import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
import kotlin.coroutines.cancellation.CancellationException
import kotlin.math.roundToInt import kotlin.math.roundToInt
fun buildBounds(points: List<Point>): Pair<Point, Point> { 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)) return Pair(Point(north, east), Point(south, west))
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable @Composable
@Preview @Preview
fun App() { fun App() {
@ -138,12 +142,17 @@ fun App() {
newCameraPosition = Pair(Point(0.0, 0.0), bounds) 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 { MaterialTheme {
BottomSheetScaffold( BottomSheetScaffold(
scaffoldState = scaffoldState, scaffoldState = scaffoldState,
sheetPeekHeight = 250.dp, sheetPeekHeight = peekHeight * peekHeightMultiplier,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
sheetContent = { Box(modifier = Modifier) }, sheetContent = { Box(modifier = Modifier) },
sheetSwipeEnabled = sheetSwipeEnabled,
) { ) {
Maps( Maps(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
@ -161,6 +170,27 @@ fun App() {
onRouteChange = { route = it } 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( Box(
Modifier.windowInsetsPadding(WindowInsets.safeContent.add(WindowInsets(bottom = extInsets))), Modifier.windowInsetsPadding(WindowInsets.safeContent.add(WindowInsets(bottom = extInsets))),
contentAlignment = Alignment.BottomEnd contentAlignment = Alignment.BottomEnd

View file

@ -11,7 +11,7 @@ androidx-espresso-core = "3.6.1"
androidx-lifecycle = "2.8.4" androidx-lifecycle = "2.8.4"
androidx-material = "1.12.0" androidx-material = "1.12.0"
androidx-test-junit = "1.2.1" androidx-test-junit = "1.2.1"
compose-multiplatform = "1.7.3" compose-multiplatform = "1.8.0-beta02"
coroutines = "1.9.0" coroutines = "1.9.0"
geo = "0.8.0" geo = "0.8.0"
junit = "4.13.2" 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-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" } 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" } 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] [plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" } androidApplication = { id = "com.android.application", version.ref = "agp" }