0Pricing
Android Academy · レッスン

マーカーとカメラ

マーカーを配置し、カメラを移動します。

「マーカーとカメラ」はCoddyKit上の無料Android Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAndroid Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Android Academyコースには全4レッスンが含まれています。

マップにマーカーを付ける

空のマップは、単なるタイルの集まりです。マーカーを追加すると、店舗やレストラン、ユーザーの目的地などの情報を表現できます。そしてカメラを動かすことで、必要な場所へ表示領域を移動できます。

このレッスンでは、マーカーの追加とカスタマイズ、クラスタへのグループ化、場所から場所へのカメラのスムーズなアニメーションを行います。

マーカーを追加する

maps-composeでは、マーカーはGoogleMapのコンテンツラムダの内部に配置するコンポーザブルです。各Markerは、位置を保持するMarkerStateを受け取ります。

import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.rememberMarkerState

@Composable
fun MapWithMarker() {
    val position = LatLng(37.7749, -122.4194)
    GoogleMap(modifier = Modifier.fillMaxSize()) {
        Marker(
            state = rememberMarkerState(position = position),
            title = "San Francisco",
            snippet = "Welcome to SF"
        )
    }
}

タイトル、スニペット、情報ウィンドウ

ユーザーがマーカーをタップすると、titleとsnippetがデフォルトの情報ウィンドウに表示されます。タップすると、タイトルが太字で、その下にスニペットが表示されます。

細かく制御したい場合は、独自のコンポーザブルコンテンツを持つMarkerInfoWindowを指定できます。

Marker(
    state = rememberMarkerState(position = LatLng(48.8584, 2.2945)),
    title = "Eiffel Tower",
    snippet = "Paris, France",
    // The info window pops up on tap by default
)

マーカーアイコンをカスタマイズする

iconパラメーターを介してBitmapDescriptorを渡すと、マーカーの見た目を変更できます。defaultMarker(hue)では標準ピンの色を変更できます。また、drawableから作成することもできます。

import com.google.android.gms.maps.model.BitmapDescriptorFactory

Marker(
    state = rememberMarkerState(position = LatLng(35.6895, 139.6917)),
    title = "Tokyo",
    icon = BitmapDescriptorFactory.defaultMarker(
        BitmapDescriptorFactory.HUE_AZURE
    )
)

データから多数のマーカーを表示する

実際のアプリでは、リストからマーカーを描画します。マップのコンテンツ内でデータをループし、各項目に対してMarkerを出力します。項目ごとに安定したキーを使用してください。

data class Place(val name: String, val latLng: LatLng)

@Composable
fun PlacesMap(places: List<Place>) {
    GoogleMap(modifier = Modifier.fillMaxSize()) {
        places.forEach { place ->
            Marker(
                state = rememberMarkerState(position = place.latLng),
                title = place.name
            )
        }
    }
}

マーカーのクリックを処理する

各MarkerはonClickラムダを受け取ります。イベントを消費してデフォルトの情報ウィンドウを抑制する場合はtrueを返し、デフォルトの動作を実行させる場合はfalseを返します。

Marker(
    state = rememberMarkerState(position = LatLng(40.7128, -74.0060)),
    title = "New York",
    onClick = {
        // handle the tap, e.g. open a detail screen
        true // consume the event
    }
)

カメラを即座に移動する

アニメーションなしで表示領域を移動するには、CameraPositionStateにカメラ位置を直接設定します。これはハードカットで、マップが瞬時に移動します。

val cameraPositionState = rememberCameraPositionState()

// Instant move
cameraPositionState.position = CameraPosition.fromLatLngZoom(
    LatLng(51.5074, -0.1278), // London
    14f
)

カメラをアニメーションさせる

洗練された操作感にするには、animate()でカメラをアニメーションさせます。これはsuspend関数なので、コルーチンスコープから起動してください。移動先はCameraUpdateで指定します。

import com.google.android.gms.maps.CameraUpdateFactory

val scope = rememberCoroutineScope()
Button(onClick = {
    scope.launch {
        cameraPositionState.animate(
            CameraUpdateFactory.newLatLngZoom(
                LatLng(48.8566, 2.3522), 13f
            ),
            durationMs = 1000
        )
    }
}) { Text("Fly to Paris") }

複数のマーカーを画面に収める

複数のマーカーを一度に表示するには、すべてのマーカーを含むLatLngBoundsを作成し、ピクセル単位のパディングを指定してnewLatLngBoundsでそこへアニメーションさせます。

import com.google.android.gms.maps.model.LatLngBounds

val bounds = LatLngBounds.Builder().apply {
    places.forEach { include(it.latLng) }
}.build()

scope.launch {
    cameraPositionState.animate(
        CameraUpdateFactory.newLatLngBounds(bounds, 100) // 100px padding
    )
}

多数のマーカーをクラスタリングする

数百個のマーカーがあると、マップが見づらくなります。maps-compose-utilsライブラリのClusteringを使うと、近くのマーカーを1つのバブルにまとめ、ズームインすると分割できます。

import com.google.maps.android.compose.clustering.Clustering

@Composable
fun ClusteredMap(items: List<MyClusterItem>) {
    GoogleMap(modifier = Modifier.fillMaxSize()) {
        Clustering(items = items)
    }
}

カメラの状態を読み取る

カメラの状態を読み取ることもできます。cameraPositionState.positionから現在のターゲットとズームが取得でき、isMovingからユーザーが現在パンしているかどうかがわかります。表示領域のデータだけを遅延読み込みする場合などに便利です。

LaunchedEffect(cameraPositionState.isMoving) {
    if (!cameraPositionState.isMoving) {
        val center = cameraPositionState.position.target
        // fetch data near `center`
    }
}

理解度チェック

カメラをジャンプさせず、1秒かけて新しい場所へ滑らかに移動させたい場合、どの方法が正しいですか?

まとめ

これで、マップを情報豊かで動的なものにできるようになりました。

  • GoogleMapのコンテンツ内にMarkerコンポーザブルを配置し、title、snippet、カスタムiconを指定します。
  • データリストからマーカーを描画し、onClickを処理します。
  • positionでカメラを即座に移動し、animate()で滑らかに移動します。
  • LatLngBoundsですべての地点を画面に収め、Clusteringで表示の混雑を減らします。

次は、実際のデバイスですべてが動作するよう、位置情報パーミッションを正しくリクエストします。

よくある質問

「マーカーとカメラ」レッスンは無料ですか?

はい。「マーカーとカメラ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Android Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Android Academyコースには全4レッスンが含まれています。

「マーカーとカメラ」で何を学びますか?

マーカーを配置し、カメラを移動します。 ブラウザで直接実行するハンズオンコードでAndroid Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Android Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAndroid Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「マーカーとカメラ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAndroid Academyレッスンでコードを書いて実行できますか?

はい。すべてのAndroid Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 地図を表示する
  2. ユーザーの位置情報を取得する
  3. マーカーとカメラ
  4. 正しい位置情報権限の扱い
← Android Academyに戻る