JetpackCompose+MapComposeにMarkerを動的に追加する(ついでに地図座標も取得するよ)
前回は、MapComposeを表示しました。
今回は、このMapComposeにMarkerを動的に追加していこうと思います。
MapComposeの下にボタンをおいて、ボタンをタップするたびに、地図にマーカーを増やしていきます。
環境
AndroidStudio:Flamingo | 2022.2.1 Patch 2
OS:macOS
ライブラリは前回と一緒ですね。
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.navigation:navigation-compose:2.7.0-beta01'
implementation platform('com.google.firebase:firebase-bom:32.1.1')
implementation 'com.google.maps.android:maps-compose:2.11.4'
implementation 'com.google.android.gms:play-services-maps:18.1.0'
Step1.「Marker追加ボタン」を追加する
地図とボタンを縦並びにしたいので、Columnを使用します。
ボタンは、地図の下に配置したいので、GoogleMapの方だけweightを指定しています。
Column {
GoogleMap(
modifier = Modifier.weight(1f),
cameraPositionState = cameraPositionState,
)
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { /* TODO */ }
) {
Text("Marker追加")
}
}
Step2.マーカーを1つ出してみる。
まずは、複数のマーカーのことは忘れて、ひとつだけ地図中央にマーカーを動的に表示します。
マーカー座標を保持するStateを定義します。
val markerItems = remember { mutableStateListOf<LatLng>() }
次に、markerItemsをMarkerとして表示する部分を書きます。
GoogleMap(
modifier = modifier,
cameraPositionState = cameraPositionState,
) {
markerItems.forEach { markerItem ->
Marker(
state = MarkerState(position = markerItem),
title = "${markerItem.latitude},${markerItem.longitude}"
)
}
}
最後にボタンクリック時にマーカー座標を設定します。
Button(
onClick = {
markerItems.add(initPos)
},
) {
Text("Marker追加")
}
(ここまでを)いざ実行
Step3.マップのロード完了を待つ
マップのロードが完了する前にいろいろ処理したくないので、マップのロードが完了したらボタンを押せるように修正します。
まずは、マップロード状態を管理するStateを定義します。
var isMapLoaded by remember { mutableStateOf(false) }
次に、MapsComposeのonMapLoadedでStateを変更します。
GoogleMap(
modifier = Modifier.weight(1f),
cameraPositionState = cameraPositionState,
onMapLoaded = {
isMapLoaded = true
}
)
最後に、このフラグを見てButtonのenabledを変化させます。
Button(
enabled = isMapLoaded,
onClick = { /* ... */ }
)
Step4.GoogleMapの表示座標(緯度経度)を取得する
マップが表示している緯度経度は、以下で取得できます。
// 地図の緯度経度領域
val latLngBounds:LatLngBounds = cameraPositionState.projection?.visibleRegion?.latLngBounds
// 地図の北東 緯度経度
val northEast:LatLng = latLngBounds.northeast
// 地図の南西 緯度経度
val southWest:LatLng = latLngBounds.southwest
ボタンのonClickで、緯度経度それぞれを10等分して、北東から南西に順番にマーカーが追加されるように計算します。
ついでに、地図が動かされている(=カメラ位置が変化している)タイミングでは、計算しないようにしました。
onClick = {
if (!cameraPositionState.isMoving) {
val latLngBounds = cameraPositionState.projection?.visibleRegion?.latLngBounds
if (latLngBounds != null) {
val northEast = latLngBounds.northeast
val southWest = latLngBounds.southwest
val latitude = northEast.latitude - ((northEast.latitude - southWest.latitude) / 10.0) * (markerItems.count() + 1)
val longitude = northEast.longitude - ((northEast.longitude - southWest.longitude) / 10.0) * (markerItems.count() + 1)
markerItems.add(LatLng(latitude, longitude))
}
}
},
いざ実行
北東から順番にマーカーが増えていきます。コード