Google Maps + Jetpack Compose: Maps, Markers & Location Guide
Google Maps integration in Jetpack Compose is handled through the maps-compose library, providing composable functions for map rendering, markers, and location drawing.
Google Map Composable
The GoogleMap composable is the foundation:
@Composable
fun MyMapScreen() {
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(
LatLng(37.7749, -122.4194), // San Francisco
12f
)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState,
properties = MapProperties(
isMyLocationEnabled = true,
mapType = MapType.NORMAL
)
)
}
Adding Markers
Use Marker or MarkerComposable for location pins:
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(
state = MarkerState(position = LatLng(37.7749, -122.4194)),
title = "San Francisco",
snippet = "California"
)
MarkerComposable(
state = MarkerState(position = LatLng(34.0522, -118.2437)),
onClick = { true }
) {
Icon(
painter = painterResource(id = R.drawable.ic_location),
contentDescription = "Location",
tint = Color.Red,
modifier = Modifier.size(32.dp)
)
}
}
Camera State Management
Manage zoom, pan, and animation:
val cameraPositionState = rememberCameraPositionState()
Button(
onClick = {
cameraPositionState.move(
CameraUpdateFactory.newLatLngZoom(
LatLng(34.0522, -118.2437),
15f
)
)
}
) {
Text("Go to LA")
}
// Listen to camera changes
LaunchedEffect(cameraPositionState.isMoving) {
if (!cameraPositionState.isMoving) {
val zoomLevel = cameraPositionState.position.zoom
println("User zoomed to level: $zoomLevel")
}
}
Current Location with FusedLocationProviderClient
Get user location:
val context = LocalContext.current
val locationClient = remember {
LocationServices.getFusedLocationProviderClient(context)
}
LaunchedEffect(Unit) {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
locationClient.lastLocation.addOnSuccessListener { location ->
if (location != null) {
val cameraUpdate = CameraUpdateFactory.newLatLngZoom(
LatLng(location.latitude, location.longitude),
13f
)
cameraPositionState.move(cameraUpdate)
}
}
}
}
Drawing Polylines & Circles
Add geographic shapes:
GoogleMap(
cameraPositionState = cameraPositionState
) {
// Polyline (route)
Polyline(
points = listOf(
LatLng(37.7749, -122.4194),
LatLng(37.7849, -122.4094),
LatLng(37.7949, -122.3994)
),
color = Color.Blue,
width = 5f
)
// Circle (radius zone)
Circle(
center = LatLng(37.7749, -122.4194),
radius = 500.0, // meters
fillColor = Color(0x33FF0000),
strokeColor = Color.Red,
strokeWidth = 2f
)
}
MapProperties Configuration
Customize map behavior and appearance:
GoogleMap(
properties = MapProperties(
isMyLocationEnabled = true,
mapType = MapType.SATELLITE,
isIndoorEnabled = true,
isTrafficEnabled = true,
isBuildingsEnabled = true,
minZoomPreference = 5f,
maxZoomPreference = 20f
),
uiSettings = MapUiSettings(
zoomControlsEnabled = true,
compassEnabled = true,
myLocationButtonEnabled = true,
scrollGesturesEnabled = true,
zoomGesturesEnabled = true
)
)
Responding to Map Clicks
Handle user interactions:
var selectedLocation by remember { mutableStateOf<LatLng?>(null) }
GoogleMap(
onMapClick = { latLng ->
selectedLocation = latLng
},
cameraPositionState = cameraPositionState
) {
selectedLocation?.let {
Marker(
state = MarkerState(position = it),
title = "Selected",
snippet = "${it.latitude}, ${it.longitude}"
)
}
}
Best Practices
-
Request Permissions - Always check
ACCESS_FINE_LOCATIONat runtime -
API Key - Store in
AndroidManifest.xmlor secure config -
Memory Management - Clean up location clients in
onCleared() -
Camera Animation - Use
newLatLngZoom()for smooth transitions - Marker Clustering - For 100+ markers, use MarkerClusterer
- Offline Support - Consider caching tile data for areas
-
Testing - Use Compose preview with mock
MapComposable
Google Maps in Compose provides powerful location-based features while maintaining Jetpack Compose's declarative paradigm.
8 Android App Templates → https://myougatheax.gumroad.com
Top comments (0)