googlemaps / googlemaps/android-maps-compose
CameraPositionState.projection lags
- Dominant language
- Kotlin
- Stars
- 1.3k
- Forks
- 181
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 18
Description
I'm using `CameraPositionState.projection` to map LatLng locations and dimensions to screen coords for plotting custom markers. I noticed that when panning the map my markers would stay at their old on-screen positions for a few seconds before jumping to the updated position; it seems like the projection is not being updated every time the view is recomposed at a new position. I found that by reading the state's `position` before `projection` I could force the update. Even if this behaviour is deliberate for reasons of efficiency I think it needs to at least be documented, because it took me a long time of tinkering to find this workaround.
#### Environment details
1. Specify the API at the beginning of the title (for example, "Places: ...")
2. OS type and version: Android 13; Evolution X 7.5 | Menudo | fajita | OFFICIAL
3. Library version and other environment information: maps-compose 2.11.4
#### Steps to reproduce
1. Use code which reads `CameraPositionState.projection` similar to the example below.
2. Run the app and pan the map.
3. Notice the marker failing to pan with the map.
#### Code example
```kotlin
@Composable
fun AngelMap(
location: LatLng,
modifier: Modifier = Modifier,
) {
val displayDensity = remember { Resources.getSystem().displayMetrics.density.toDouble() }
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition(
location,
19.0F,
0.0F,
0.0F
)
val styleOptions = remember { MapStyleOptions(mapStyleOptions) }
val mapProperties = MapProperties(
isBuildingEnabled = true,
isIndoorEnabled = true,
isMyLocationEnabled = false,
mapStyleOptions = styleOptions,
mapType = MapType.NORMAL,
)
val mapUiSettings = remember { MapUiSettings() }
Box(modifier = modifier) {
GoogleMap(modifier = Modifier.matchParentSize(),
properties = mapProperties,
uiSettings = mapUiSettings,
cameraPositionState = cameraPositionState,
)
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Top,
) {
// Uncommenting the following line fixes the issue
// cameraPositionState.position
cameraPositionState.projection?.let { projection ->
// In my real app additional markers are plotted in a loop
AngelMapMarker(
location = location,
size = 10,
projection = projection,
displayDensity = displayDensity,
)
}
}
}
}
@Composable
fun AngelMapMarker(
location: LatLng,
size: Double,
projection: Projection,
displayDensity: Double,
) {
val cornerPolar = location.addingMetres(north = size, east = -size)
val centrePx = projection.toScreenLocation(location)
val cornerPx = projection.toScreenLocation(cornerPolar)
val dxPx = centrePx.x - cornerPx.x
val dyPx = centrePx.y - cornerPx.y
val radiusPx = sqrt((dxPx * dxPx + dyPx * dyPx).toDouble())
val radiusDp = (radiusPx / displayDensity).dp
val cornerXDp = (cornerPx.x.toDouble() / displayDensity).dp
val cornerYDp = (cornerPx.y.toDouble() / displayDensity).dp
// fillColour and strokeColour also need to be defined
// Outer circle
Box(
modifier = Modifier
.offset(cornerXDp, cornerYDp)
.size(radiusDp)
.clip(CircleShape)
.background(fillColour)
.border(width = 2.dp, color = strokeColour, shape = CircleShape),
contentAlignment = Alignment.Center,
) {
// Other stuff inside the circle
}
}
```
#### Stack trace
N/A
Contributor guide
Assessment
This issue has not been assessed yet.