0
0

More than 1 year has passed since last update.

MapComposeにMarkerを動的に追加する

Last updated at Posted at 2023-07-03

JetpackCompose+MapComposeにMarkerを動的に追加する(ついでに地図座標も取得するよ)

前回は、MapComposeを表示しました。
今回は、このMapComposeにMarkerを動的に追加していこうと思います。

MapComposeの下にボタンをおいて、ボタンをタップするたびに、地図にマーカーを増やしていきます。

ゴールイメージは以下の画像の様になります。
map_add_marker_2_AdobeExpress.gif

環境

AndroidStudio:Flamingo | 2022.2.1 Patch 2
OS:macOS

ライブラリは前回と一緒ですね。

build.gradle
    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を指定しています。

GoogleMapsScreen.kt
Column {
    GoogleMap(
        modifier = Modifier.weight(1f),
        cameraPositionState = cameraPositionState,
    )
    Button(
        modifier = Modifier.fillMaxWidth(),
        onClick = { /* TODO */ }
    ) {
        Text("Marker追加")
    }
}

Step2.マーカーを1つ出してみる。

まずは、複数のマーカーのことは忘れて、ひとつだけ地図中央にマーカーを動的に表示します。
マーカー座標を保持するStateを定義します。

GoogleMapsScreen.kt
val markerItems = remember { mutableStateListOf<LatLng>() }

次に、markerItemsをMarkerとして表示する部分を書きます。

GoogleMapsScreen.kt
GoogleMap(
    modifier = modifier,
    cameraPositionState = cameraPositionState,
) {
    markerItems.forEach { markerItem ->
        Marker(
            state = MarkerState(position = markerItem),
            title = "${markerItem.latitude},${markerItem.longitude}"
        )
    }
}

最後にボタンクリック時にマーカー座標を設定します。

GoogleMapsScreen.kt
Button(
    onClick = {
        markerItems.add(initPos)
    },
) {
    Text("Marker追加")
}

(ここまでを)いざ実行

ボタンを押すと、地図の真ん中にマーカーが増えました。
map_add_marker_1_AdobeExpress.gif

Step3.マップのロード完了を待つ

マップのロードが完了する前にいろいろ処理したくないので、マップのロードが完了したらボタンを押せるように修正します。

まずは、マップロード状態を管理するStateを定義します。

GoogleMapsScreen.kt
var isMapLoaded by remember { mutableStateOf(false) }

次に、MapsComposeのonMapLoadedでStateを変更します。

GoogleMapsScreen.kt
GoogleMap(
    modifier = Modifier.weight(1f),
    cameraPositionState = cameraPositionState,
    onMapLoaded = {
        isMapLoaded = true
    }
)

最後に、このフラグを見てButtonのenabledを変化させます。

GoogleMapsScreen.kt
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等分して、北東から南西に順番にマーカーが追加されるように計算します。
ついでに、地図が動かされている(=カメラ位置が変化している)タイミングでは、計算しないようにしました。

GoogleMapsScreen.kt
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))
        }
    }
},

いざ実行

北東から順番にマーカーが増えていきます。コード

map_add_marker_2_AdobeExpress.gif

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0