microsoft / MapsSDK-Native

This repository contains samples, documentation and releases history for the Bing Maps SDK for Android and iOS.
MIT License
40 stars 23 forks source link

Please add a Jetpack Compose sample #58

Open tscholze opened 2 years ago

tscholze commented 2 years ago

Problem The current sample features an "old" way of developing for Android. Yes, this approach is still valid and works like a charm, but it would be great to adopt to the future and provide samples using Kotlin and Jetpack Compose

Example

// MARK: - Internal composable views -

@Composable
fun BingMap(lat: Double, lng: Double) {
    val map = rememberBingMapViewWithLifecycle()
    BingMapContainer(map = map, lat = lat, lng = lng)
}

// MARK: - Private composable views -

@Composable()
private fun BingMapContainer(map: MapView, lat: Double, lng: Double) {

    LaunchedEffect(map) {
        val point = Geopoint(lat, lng)
        map.setScene(MapScene.createFromLocation(point), MapAnimationKind.NONE)
    }

    val coroutineScope = rememberCoroutineScope()

    AndroidView(factory = { map }) {
        coroutineScope.launch {
            it.centerTo(lat = lat, lng = lng)
        }
    }
}

@Composable
private fun rememberBingMapViewWithLifecycle(): MapView {
    val context = LocalContext.current
    val map = remember { MapView(context) }
    map.setCredentialsKey(CREDENTIALS_KEY)

    val observer = rememberBingMapViewLifecycleObserver(map)
    val lifecycle = LocalLifecycleOwner.current.lifecycle

    DisposableEffect(lifecycle) {
        lifecycle.addObserver(observer)

        onDispose {
            lifecycle.removeObserver(observer)
        }
    }

    return map
}

@Composable
private fun rememberBingMapViewLifecycleObserver(map: MapView): LifecycleEventObserver {
    return remember(map) {
        LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_START -> map.onStart()
                Lifecycle.Event.ON_STOP -> map.onStop()
                Lifecycle.Event.ON_DESTROY -> map.onDestroy()
                else -> Unit // nop
            }
        }
    }
}

// MARK: - Extension -

fun MapView.centerTo(lat: Double, lng: Double) {
    val point = Geopoint(lat, lng)
    setScene(MapScene.createFromLocation(point), MapAnimationKind.NONE)
}