Google Map

Initial Position

Let's make the app more friendly by automatically moving to that marker position.

First, we define a CameraPosition to indicate where we want to jump to on the map. Think of this as a literal camera, pointing to a LatLng from a specific bearing and tilt, zoomed in/out to a certain factor.

We define a CameraPositionState similar to our MarkerState to hold the data for the map camera. It's position is initialized to our defaultCameraPosition, but as the user interacts with the map (panning, zooming, rotating, etc) this state will be updated.

show in full file app/src/main/java/com/androidbyexample/compose/google/google/maps/MainActivity.kt
// ...
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        setContent {
            GoogleMapsTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    val googleHQ = LatLng(37.42423291057923, -122.08811454627153)

                    val defaultCameraPosition = CameraPosition.fromLatLngZoom(googleHQ, 11f)

                    val cameraPositionState = rememberCameraPositionState {
                        position = defaultCameraPosition
                    }
                    GoogleMapDisplay(
                        place = googleHQ,
                        placeDescription = "Google HQ",
                        cameraPositionState = cameraPositionState,
                        modifier = Modifier.padding(innerPadding).fillMaxSize(),
                    )
                }
            }
        }
    }
}

Where should we define these state? Only as high in the call hierarchy as needed. Pretend that we have a ViewModel that needs to know when the camera moves; defining the cameraPositionState in onCreate as we're doing here gives us access to that state. If instead we defined it inside GoogleMapView, we would only have access to that state inside GoogleMapView (unless we passed an onCameraChange function that could be used to send out changed camera values).

Pulling state up out of functions like this is called "State Hoisting".

We use that state inside the GoogleMap call

show in full file app/src/main/java/com/androidbyexample/compose/google/google/maps/GoogleMapDisplay.kt
// ...

@Composable
fun GoogleMapDisplay(
    place: LatLng,
    placeDescription: String,
    cameraPositionState: CameraPositionState,
    modifier: Modifier,
) {
    val placeState =
        rememberMarkerState(key = place.toString(), position = place)

    GoogleMap(
        cameraPositionState = cameraPositionState,
        modifier = modifier,
    ) {
        // ...
    }
}

Now when we run the application, we see the map centered on Google HQ.


All code changes

CHANGED: app/src/main/java/com/androidbyexample/compose/google/google/maps/GoogleMapDisplay.kt
package com.androidbyexample.compose.google.google.maps

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.CameraPositionState
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.MarkerInfoWindowContent
import com.google.maps.android.compose.rememberMarkerState

@Composable fun GoogleMapDisplay( place: LatLng, placeDescription: String,
cameraPositionState: CameraPositionState, modifier: Modifier, ) {
val placeState = rememberMarkerState(key = place.toString(), position = place)
GoogleMap( cameraPositionState = cameraPositionState,
modifier = modifier,
) {
MarkerInfoWindowContent( state = placeState, title = placeDescription, onClick = { placeState.showInfoWindow() true } )
} }
CHANGED: app/src/main/java/com/androidbyexample/compose/google/google/maps/MainActivity.kt
package com.androidbyexample.compose.google.google.maps

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.androidbyexample.compose.google.google.maps.ui.theme.GoogleMapsTheme
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.rememberCameraPositionState

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            GoogleMapsTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
val googleHQ = LatLng(37.42423291057923, -122.08811454627153)
val defaultCameraPosition = CameraPosition.fromLatLngZoom(googleHQ, 11f)
val cameraPositionState = rememberCameraPositionState { position = defaultCameraPosition } GoogleMapDisplay( place = googleHQ, placeDescription = "Google HQ", cameraPositionState = cameraPositionState, modifier = Modifier.padding(innerPadding).fillMaxSize(), )
} } } } }