Home > OS >  How show loading spinner in Jetpack Compose while Google Maps load?
How show loading spinner in Jetpack Compose while Google Maps load?

Time:01-25

Following several tutorials on the internet, I have managed to paint a Google map in my application:

@Composable
fun MyMap(
    lat: Double,
    lon: Double
) {

    val mapView = rememberMapViewWithLifeCycle()

    Column(
        modifier = Modifier
            .background(Color.White)
    ) {
        AndroidView(
            { mapView }
        ) { mapView ->
            CoroutineScope(Dispatchers.Main).launch {
                val map = mapView.awaitMap()
                map.uiSettings.isZoomControlsEnabled = false
                val destination = LatLng(lat, lon)
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(destination, 16f))
                val markerOptionsDestination = MarkerOptions()
                    .position(destination)
                map.addMarker(markerOptionsDestination)
                map.mapType = com.google.android.libraries.maps.GoogleMap.MAP_TYPE_HYBRID
            }
        }
    }
}

@Composable
fun rememberMapViewWithLifeCycle(): MapView {
    val context = LocalContext.current
    val mapView = remember {
        MapView(context).apply {
            id = R.id.map_frame
        }
    }
    val lifeCycleObserver = rememberMapLifecycleObserver(mapView)
    val lifeCycle = LocalLifecycleOwner.current.lifecycle
    DisposableEffect(lifeCycle) {
        lifeCycle.addObserver(lifeCycleObserver)
        onDispose {
            lifeCycle.removeObserver(lifeCycleObserver)
        }
    }

    return mapView
}

@Composable
fun rememberMapLifecycleObserver(mapView: MapView): LifecycleEventObserver =
    remember(mapView) {
        LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_CREATE -> mapView.onCreate(Bundle())
                Lifecycle.Event.ON_START -> mapView.onStart()
                Lifecycle.Event.ON_RESUME -> mapView.onResume()
                Lifecycle.Event.ON_PAUSE -> mapView.onPause()
                Lifecycle.Event.ON_STOP -> mapView.onStop()
                Lifecycle.Event.ON_DESTROY -> mapView.onDestroy()
                else -> throw IllegalStateException()
            }
        }
    }

I load this composable from another composable where I have more elements, like texts and so on:

@Composable
fun MyMain() {
Box(
    modifier = Modifier
        .fillMaxWidth()
        .size(300.dp)
) {
    MyMap(lat, lon)
}
}

The map takes time to load, not long, maybe 1 second or less. But I would like the MyMain composable instead of being empty box (the box that contains the map) that second, to show a loading spinner. How could I implement this?

CodePudding user response:

You can probably do something like this:
If the map isn't actually fully loaded after mapView.awaitMap() try replacing the line with a delay(1000). (or longer than 1000 ms)

@Composable
fun MyMap(
    lat: Double,
    lon: Double,
) {
    val mapView = rememberMapViewWithLifeCycle()

    var isMapLoading by remember { mutableStateOf(true) }

    LaunchedEffect(mapView) {
        mapView.awaitMap()
        isMapLoading = false
    }

    Box {
        AndroidView(
            { mapView }
        ) { mapView ->
            CoroutineScope(Dispatchers.Main).launch {
                val map = mapView.awaitMap()
                map.uiSettings.isZoomControlsEnabled = false
                val destination = LatLng(lat, lon)
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(destination, 16f))
                val markerOptionsDestination = MarkerOptions()
                    .position(destination)
                map.addMarker(markerOptionsDestination)
                map.mapType = com.google.android.libraries.maps.GoogleMap.MAP_TYPE_HYBRID
            }
        }
        if (isMapLoading) {
            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier
                    .matchParentSize()
                    .background(Color.White)
            ) {
                CircularProgressIndicator()
            }
        }
    }
}
  •  Tags:  
  • Related