はじめに
- Maps SDK for Android の MapView を使って Jetpack Compose で構成した画面に Google Map を表示する方法です
- 今後使うかも知れないので、ここに残しておくことにしました。どなたかのお役に立てば嬉しいです
- ちなみに元ネタは下記の Codelab です。気になった方はトライしてみてください
- 従来の Android View で
MapView
を使うやり方については、以前こちらの記事で共有させて頂きました- かなり前の記事ですが、基本的には今でも同じ方法が使えるようです
実装
ポイントは以下の2点になるかと思います
- ライフサイクルと同期した
MapView
を生成し保持する - コンポーザブルで
MapView
を 配置する
ライフサイクルと同期した MapView を生成し保持する
-
以前の記事 にも書きましたが、
MapView
はActivity
やFragment
のライフサイクルと同期し、イベントに応じて適切なメソッドが呼び出されなくてはなりません-
Activity.onCreate()
の中でMapView.onCreate()
が呼ばれなくてはならない、といった具合 - MapView のリファレンス にもその旨の記述 (『You must call this method from the parent Activity/Fragment's corresponding method』)があります
-
- ライフサイクルとの同期は、 LifecycleEventObserver と
DisposableEffect
を組み合わせて実現するのがよさそうです-
DisposableEffect
についてはこちらが詳しいです
-
サンプルコード
MapView
を保持/参照するためのコンポーザブルが以下です
(ほぼ元ネタそのままなので、必要に応じて手を入れるなどして頂ければと思います)
@Composable
fun rememberMapViewWithLifecycle(): MapView {
val context = LocalContext.current
val mapView = remember {
MapView(context).apply { id = R.id.map_view_id }
}
val lifeCycle = LocalLifecycleOwner.current.lifecycle
DisposableEffect(key1 = lifeCycle, key2 = mapView) {
val lifecycleObserver = 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()
}
}
lifeCycle.addObserver(lifecycleObserver)
onDispose {
lifeCycle.removeObserver(lifecycleObserver)
}
}
return mapView
}
コンポーザブルで MapView を 配置する
-
MapView
が取得できれば、AndroidView コンポーザブル を使って配置できます
サンプルコード
JR大阪駅にマーカーを立てて、 16.0f のズーム率でマップを表示したものです
val mapView = rememberMapViewWithLifecycle()
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { mapView },
) { view ->
view.getMapAsync {
val position = LatLng(34.702473, 135.495926)
val zoom = 16.0f
it.addMarker(
MarkerOptions().position(position).title("Sample Marker")
)
it.moveCamera(
CameraUpdateFactory.newCameraPosition(
CameraPosition.Builder().apply {
target(position)
zoom(zoom)
}.build()
)
)
}
}
実行結果
追記
- 自分なりに Compose + MapView の実装を試みたもの を GitHub で公開しております
- このエントリに記載したこと含め、何かしらの誤りや改善点などあれば指摘頂けますと有難いです