Background
Integrating Google Maps into your Jetpack Compose application can significantly enhance the user experience by providing interactive and dynamic geographical information.
In this blog post, we’ll show you how to add a map to your app, control the camera position, and draw various elements on the map. From setting targets and animating zoom levels to handling boundaries and drawing markers, circles, and polylines, you’ll learn how to leverage the powerful features of Google Maps in Jetpack Compose.
If you’re looking for a practical implementation of the techniques we will discuss in this blog, check out GroupTrack open-source location sharing and tracking application. Feel free to explore and use it as a reference for your projects.
Let’s dive in and start integrating Google Maps into your app!
Configure a Map
Requirements
- A Google account with billing
- A Map API key — follow this guide to get your API key
Add Dependency
Add the following dependency to your module gradle.build file,
implementation 'com.google.maps.android:maps-compose:X.X.X'
Add your Map API key in the manifest file,
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${YOUR_MAPS_API_KEY}" />
Add GoogleMap composable
To render a map you need to use Google Composable. Let's have a quick look at it.
@Composable
public fun GoogleMap(
mergeDescendants: Boolean = false,
modifier: Modifier = Modifier,
cameraPositionState: CameraPositionState = rememberCameraPositionState(),
contentDescription: String? = null,
googleMapOptionsFactory: () -> GoogleMapOptions = { GoogleMapOptions() },
properties: MapProperties = DefaultMapProperties,
locationSource: LocationSource? = null,
uiSettings: MapUiSettings = DefaultMapUiSettings,
indoorStateChangeListener: IndoorStateChangeListener = DefaultIndoorStateChangeListener,
onMapClick: ((LatLng) -> Unit)? = null,
onMapLongClick: ((LatLng) -> Unit)? = null,
onMapLoaded: (() -> Unit)? = null,
onMyLocationButtonClick: (() -> Boolean)? = null,
onMyLocationClick: ((Location) -> Unit)? = null,
onPOIClick: ((PointOfInterest) -> Unit)? = null,
contentPadding: PaddingValues = NoPadding,
content: (@Composable @GoogleMapComposable () -> Unit)? = null,
)
Basic Setup:
-
modifier
: Apply visual styling to your map container. -
cameraPositionState
: Manage the map's viewpoint (zoom level and location).
Customization Options:
-
googleMapOptionsFactory
: Fine-tune the initial map behavior (e.g., zoom controls, map type). -
properties
: Set additional map attributes like compass position and zoom gestures. -
locationSource
: Integrate location tracking features (if needed). -
uiSettings
: Control UI elements like zoom buttons or the compass.
Adding Content:
-
contentPadding
: Define padding around the map edges to avoid overlapping with other UI elements. -
content
: This is where you add your visual elements, like markers or overlays, on top of the map.
Let's first render the Map, and then talk about map properties, type and UI settings.
@Composable
fun SimpleMap() {
val latLng = LatLng(-33.852334, 151.211245) // Any Coordinates
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(latLng, 14f) // Set zoom level
}
GoogleMap(
modifier = Modifier.fillMaxSize(), // Fill the entire screen
cameraPositionState = cameraPositionState
)
}
Run your app and voila! You should see a centered map of Sydney.
Map Properties
Now, let’s delve deeper into the MapProperties class, which allows you to refine your map's visual and interactive aspects.
public class MapProperties(
public val isBuildingEnabled: Boolean = false,
public val isIndoorEnabled: Boolean = false,
public val isMyLocationEnabled: Boolean = false,
public val isTrafficEnabled: Boolean = false,
public val latLngBoundsForCameraTarget: LatLngBounds? = null,
public val mapStyleOptions: MapStyleOptions? = null,
public val mapType: MapType = MapType.NORMAL,
public val maxZoomPreference: Float = 21.0f,
public val minZoomPreference: Float = 3.0f,
)
Building and Indoor Maps:
-
isBuildingEnabled
: Show or hide 3D building overlays (default: false). -
isIndoorEnabled
: Enable viewing indoor maps of supported locations (default: false).
Location and Traffic:
-
isMyLocationEnabled
: Allow users to see their current location on the map (default: false). -
isTrafficEnabled
: Overlay real-time traffic information on the map (default: false).
Map Appearance and Behavior:
-
latLngBoundsForCameraTarget
: Define a specific area for the map to focus on initially. -
mapStyleOptions
: Apply custom map styles to change the visual appearance (e.g., map theme). -
mapType
: Choose between different map types like normal, satellite, or hybrid (default: NORMAL). -
maxZoomPreference
: Set the maximum zoom level users can reach (default: 21.0f). -
minZoomPreference
: Set the minimum zoom level users can reach (default: 3.0f).
Let’s render our previous map along with map properties:
@Composable
fun SimpleMap() {
val latLng = LatLng(-33.852334, 151.211245) // Any Coordinates
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(latLng, 14f) // Set zoom level
}
val mapProperties = remember(isDarkMode) {
MapProperties(
latLngBoundsForCameraTarget = LatLngBounds(
latLng,
LatLng(-33.852334 + 0.1, 151.211245 + 0.1)
),
mapType = MapType.HYBRID,
)
}
GoogleMap(
modifier = Modifier.fillMaxSize(), // Fill the entire screen
cameraPositionState = cameraPositionState,
properties = mapProperties,
)
}
So, after applying the above mapProperties, your app will look like this:
To read the full version, please visit canopas blog.
Conclusion
If you like what you read, be sure to hit 💖 button! — as a writer it means the world!
I encourage you to share your thoughts in the comments section below or reach us at Canopas Twitter handle @canopas_eng with your content or feedback.
Your input not only enriches our content but also fuels our motivation to create more valuable and informative articles for you.
Happy coding! 👋