0
0

More than 1 year has passed since last update.

MapComposeのPolylineを動的に追加する

Posted at

JetpackCompose+MapComposeにPolylineを動的に追加する

前回は、MapComposeにMarkerを動的に追加しました。
今回は、Polylineを追加します。

まずは、地図上のタップ位置に対してPolylineを伸ばしていきます。
次に、スクリーン座標を地図座標表に変換してから、Polyline化していきます。

環境

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.Polylineを追加する

地図上のタップ位置をPolyline描画します。

まず、Polylineのpoints座標を保持するState定義を追加します。

Markerの時とは異なり、Stateの定義には「mutableStateOf」を使用します。
誤) val markerItems = remember { mutableStateListOf() }

正) var polylineItems by remember { mutableStateOf>(listOf()) }

GoogleMapsScreen.kt
var polylineItems by remember { mutableStateOf<List<LatLng>>(listOf()) }

次に、マップのonMapClickで一覧更新を行う記述を追加します。

GoogleMapsScreen.kt
GoogleMap(
    modifier = modifier,
    cameraPositionState = cameraPositionState,
    onMapLoaded = onMapLoaded,
    onMapClick = { latLng ->
        polylineItems = polylineItems + latLng
    },
) {

最後に、ポイントが2点以上となったらPolylineを描画するように記述します。

GoogleMapsScreen.kt
GoogleMap(/* ... */) {
    /* ... */
    if (polylineItems.count() > 1) {
        Polyline(
            points = polylineItems,
        )
    }
}

いざ実行

ここまでのコードはこちら
map_polyline_1_AdobeExpress.gif

Step2.スクリーン座標を取得する

まず、スクリーンのタップ位置座標を取得するために、GoogleMapと同じ大きさ・同じ位置のBoxを配置します。

検証を目的にBoxを配置しています。
BoxをGoogleMapの上に配置することで、GoogleMapが拾っていたイベントをすべてBoxが取得するようになりますので、GoogleMapのズームやカメラ移動などは一切効かない状態になります。

GoogleMapsScreen.kt
Column {
    Box(modifier = Modifier.weight(1f).fillMaxSize()) {
        GoogleMap(
            modifier = Modifier.matchParentSize(),
            /* ... */
        )

        // GoogleMapと同じサイズ・位置のBox
        Box(modifier = Modifier.matchParentSize())
    }
    Buttons(
        modifier = Modifier.fillMaxWidth(),
        /* ... */
    )
}

GoogleMap()の下の行に追加したBoxが、タップイベントを拾うためのBoxです。
このBoxのmodifierにpointerInputを追加します。

GoogleMapsScreen.kt
Box(
    modifier = Modifier
        .matchParentSize()
        .pointerInput(Unit) {
            detectTapGestures(
                onPress = { offset ->
                    if (!cameraPositionState.isMoving) {
                        val pressedLatLng = cameraPositionState.projection?.fromScreenLocation(Point(offset.x.toInt(), offset.y.toInt()))
                        if (pressedLatLng != null) {
                            polylineItems = polylineItems + pressedLatLng
                        }
                    }
                },
            )
        },
)

cameraPositionState.projection?.fromScreenLocationがスクリーン座標と緯度経度の変換を行う関数です。

いざ実行

コードはこちら
map_polyline_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