googlemaps / googlemaps/android-maps-compose

CameraPositionState.projection lags

Open
#314 1 comment 2 reactions 0 assignees View on GitHub
priority: p4 type: bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.