kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
feat(map): allow map to follow phone bearing (#3002)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>pull/3005/head
rodzic
93e7eb3aa0
commit
91ce6c5b93
|
|
@ -190,6 +190,7 @@ fun MapView(
|
|||
|
||||
// Location tracking state
|
||||
var isLocationTrackingEnabled by remember { mutableStateOf(false) }
|
||||
var followPhoneBearing by remember { mutableStateOf(false) }
|
||||
|
||||
LocationPermissionsHandler { isGranted -> hasLocationPermission = isGranted }
|
||||
|
||||
|
|
@ -224,11 +225,27 @@ fun MapView(
|
|||
if (isLocationTrackingEnabled) {
|
||||
locationResult.lastLocation?.let { location ->
|
||||
val latLng = LatLng(location.latitude, location.longitude)
|
||||
val cameraUpdate =
|
||||
if (followPhoneBearing) {
|
||||
val bearing =
|
||||
if (location.hasBearing()) {
|
||||
location.bearing
|
||||
} else {
|
||||
cameraPositionState.position.bearing
|
||||
}
|
||||
CameraUpdateFactory.newCameraPosition(
|
||||
CameraPosition.Builder()
|
||||
.target(latLng)
|
||||
.zoom(cameraPositionState.position.zoom)
|
||||
.bearing(bearing)
|
||||
.build(),
|
||||
)
|
||||
} else {
|
||||
CameraUpdateFactory.newLatLngZoom(latLng, cameraPositionState.position.zoom)
|
||||
}
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
cameraPositionState.animate(
|
||||
CameraUpdateFactory.newLatLngZoom(latLng, cameraPositionState.position.zoom),
|
||||
)
|
||||
cameraPositionState.animate(cameraUpdate)
|
||||
} catch (e: IllegalStateException) {
|
||||
debug("Error animating camera to location: ${e.message}")
|
||||
}
|
||||
|
|
@ -260,7 +277,6 @@ fun MapView(
|
|||
}
|
||||
}
|
||||
|
||||
// Clean up location tracking on disposal
|
||||
DisposableEffect(Unit) { onDispose { fusedLocationClient.removeLocationUpdates(locationCallback) } }
|
||||
|
||||
val allNodes by
|
||||
|
|
@ -344,7 +360,7 @@ fun MapView(
|
|||
zoomControlsEnabled = true,
|
||||
mapToolbarEnabled = true,
|
||||
compassEnabled = false,
|
||||
myLocationButtonEnabled = false, // Disabled - we use custom location button
|
||||
myLocationButtonEnabled = false,
|
||||
rotationGesturesEnabled = true,
|
||||
scrollGesturesEnabled = true,
|
||||
tiltGesturesEnabled = true,
|
||||
|
|
@ -574,46 +590,30 @@ fun MapView(
|
|||
isLocationTrackingEnabled = isLocationTrackingEnabled,
|
||||
onToggleLocationTracking = {
|
||||
if (hasLocationPermission) {
|
||||
if (!isLocationTrackingEnabled) {
|
||||
// When enabling tracking, get current location and center on it
|
||||
try {
|
||||
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
|
||||
location?.let {
|
||||
val latLng = LatLng(it.latitude, it.longitude)
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
cameraPositionState.animate(
|
||||
CameraUpdateFactory.newLatLngZoom(latLng, 16f),
|
||||
)
|
||||
} catch (e: IllegalStateException) {
|
||||
debug("Error centering camera on location: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: SecurityException) {
|
||||
debug("Location permission not available: ${e.message}")
|
||||
}
|
||||
}
|
||||
isLocationTrackingEnabled = !isLocationTrackingEnabled
|
||||
if (!isLocationTrackingEnabled) {
|
||||
followPhoneBearing = false
|
||||
}
|
||||
}
|
||||
},
|
||||
bearing = cameraPositionState.position.bearing,
|
||||
onOrientNorth = {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
val currentPosition = cameraPositionState.position
|
||||
val newCameraPosition =
|
||||
CameraPosition.Builder(currentPosition)
|
||||
.bearing(0f) // Orient to north
|
||||
.build()
|
||||
cameraPositionState.animate(CameraUpdateFactory.newCameraPosition(newCameraPosition))
|
||||
debug("Oriented map to north")
|
||||
} catch (e: IllegalStateException) {
|
||||
debug("Error orienting map to north: ${e.message}")
|
||||
onCompassClick = {
|
||||
if (isLocationTrackingEnabled) {
|
||||
followPhoneBearing = !followPhoneBearing
|
||||
} else {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
val currentPosition = cameraPositionState.position
|
||||
val newCameraPosition = CameraPosition.Builder(currentPosition).bearing(0f).build()
|
||||
cameraPositionState.animate(CameraUpdateFactory.newCameraPosition(newCameraPosition))
|
||||
debug("Oriented map to north")
|
||||
} catch (e: IllegalStateException) {
|
||||
debug("Error orienting map to north: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
followPhoneBearing = followPhoneBearing,
|
||||
)
|
||||
}
|
||||
if (showLayersBottomSheet) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package com.geeksville.mesh.ui.map.components
|
|||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.LocationDisabled
|
||||
import androidx.compose.material.icons.filled.Navigation
|
||||
import androidx.compose.material.icons.outlined.Layers
|
||||
import androidx.compose.material.icons.outlined.Map
|
||||
import androidx.compose.material.icons.outlined.MyLocation
|
||||
|
|
@ -55,7 +56,8 @@ fun MapControlsOverlay(
|
|||
isLocationTrackingEnabled: Boolean = false,
|
||||
onToggleLocationTracking: () -> Unit = {},
|
||||
bearing: Float = 0f,
|
||||
onOrientNorth: () -> Unit = {},
|
||||
onCompassClick: () -> Unit = {},
|
||||
followPhoneBearing: Boolean,
|
||||
) {
|
||||
HorizontalFloatingToolbar(
|
||||
modifier = modifier,
|
||||
|
|
@ -63,7 +65,7 @@ fun MapControlsOverlay(
|
|||
leadingContent = {},
|
||||
trailingContent = {},
|
||||
content = {
|
||||
CompassButton(onOrientNorth = onOrientNorth, bearing = bearing)
|
||||
CompassButton(onClick = onCompassClick, bearing = bearing, isFollowing = followPhoneBearing)
|
||||
if (showFilterButton) {
|
||||
Box {
|
||||
MapButton(
|
||||
|
|
@ -117,14 +119,14 @@ fun MapControlsOverlay(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun CompassButton(onOrientNorth: () -> Unit, bearing: Float) {
|
||||
val icon = Icons.Outlined.Navigation
|
||||
private fun CompassButton(onClick: () -> Unit, bearing: Float, isFollowing: Boolean) {
|
||||
val icon = if (isFollowing) Icons.Filled.Navigation else Icons.Outlined.Navigation
|
||||
|
||||
MapButton(
|
||||
modifier = Modifier.rotate(-bearing),
|
||||
icon = icon,
|
||||
iconTint = MaterialTheme.colorScheme.StatusRed.takeIf { bearing == 0f },
|
||||
contentDescription = stringResource(id = R.string.orient_north),
|
||||
onClick = onOrientNorth,
|
||||
onClick = onClick,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue