Navigation SDK for AndroidのDrop-In UI
はじめに
この記事ではMapbox Navigation SDK for Android v2におけるDrop-In UIの使い方について紹介します。
Drop-In UIとは
Drop-In UIとは、ナビゲーションに関する機能が全て詰め込まれたView機能のことです。アプリケーション側ではそのViewを読み込むだけで経路探索、経路表示、ターン・バイ・ターンナビゲーション等ナビゲーションに必要なすべての機能を使用できます。
ちなみに、以前こちらの記事で以下のように記述していました。
例えば、v1ではViewを継承したNavigationViewが実装されていました。これを使うことで、全部入りのナビゲーションはこのサンプルのように少ない記述量で作成することができました。これに対し、v2ではNavigationViewが提供されません。代わりに、ナビゲーションのための各パーツが提供されており、自身でそれらを組み合わせて使います。v1におけるこのサンプルがイメージとしては近いです。
この後v2.4.0でDrop-In UIが実装されたにも関わらず、記事のアップデートを行っておりませんでした。そこで、少し遅くなりましたが今回はDrop-In UI (NavigationView
)の使い方について見ていきます。
Drop-In UIに関する詳細は以下のドキュメントをご参照ください。
v2におけるDrop-In UIの特徴
v0, v1のNavigationView
では経路探索に関するUIが含まれておらず、自分で実装する必要がありました。それに対しv2のNavigationView
は経路探索のUIも実装されているため、特にカスタマイズを行わない場合にはKotlinのコードを書く必要すらありません。
Drop-In UIのサンプルコード
通常、SDKの使い方はSDKに同梱されているサンプルコードが一番参考になります。しかし、Drop−In UIに関してはSDKにサンプルが同梱されておりません。かわりに、以下のExampleのプロジェクトにサンプルがたくさんあります。
注意事項
テストをする際には課金の発生にご注意ください。Navigation SDK v2はMAU課金とTrip課金の両方が適用されます。MAU課金は100デバイスまで無料です。Trip課金は主にナビゲーション回数に対する課金で1000回までは無料です。特にTrip課金の方は複数の端末で何度もナビゲーションを行うと到達しうる回数なのでご注意ください。詳細はこちらのサイトをご参照ください
ちなみに、Navigation SDK v1はMAU課金のみで、10デバイスまで無料です。
最も簡単なケース
準備
ドキュメントサイトのInstallationの指示通りに設定を行います。
具体的には以下の点を設定しておくと良いでしょう。
- シークレットトークンの設定
- パブリックトークンの設定
- 依存関係の設定
コード入手先
ここで作成したサンプルコードは以下から入手可能です。
手元で試す際にはRawDropinUi/app/src/main/res/values/strings.xml
のYOUR_MAPBOX_ACCESS_TOKEN
の部分をご自身のパブリックトークンに変更してください。
レイアウト
以下のコンポーネントをactivity_main.xml
に記述します。
<com.mapbox.navigation.dropin.NavigationView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/navigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:accessToken="@string/mapbox_access_token"
xmlns:app="http://schemas.android.com/apk/res-auto">
</com.mapbox.navigation.dropin.NavigationView>
結果
実行すると以下のように経路探索からターン・バイ・ターンナビゲーションまで使用できることが確認できます。
最も単純なケースではKotlinのコードを書く必要がありません。ある意味、ノーコードですね。
Route Replay (シミュレーション)を使用する
開発途中のデバッグでは、経路を設定した際にその経路に沿って自動的に自車位置を順次移動させたいと思うかもしれません。そんなときに便利なのがRoute Replay機能です。この機能をONにすると、経路に沿ったGPS位置がNavigation SDK内部で順次作成され、それに応じて自車位置が移動します。シミュレーションモード的なイメージです。
使用するにはonCreate
メソッドに以下を追加してください。
val navigationView: NavigationView = findViewById(R.id.navigationView)
navigationView.api.routeReplayEnabled(true)
ただし、v2.12.0〜v2.13.2ではRoute Replayが正常に機能しません。2023年6月25日現在で最新のv2.14.0を使用してください。
カスタマイズする
NavigationView
は地図のスタイルのみならずナビゲーションで表示しているUIも柔軟にカスタマイズ可能です。
コード入手先
ここで作成したサンプルコードは以下から入手可能です。
手元で試す際にはCustomizedDropinUi/app/src/main/res/values/strings.xml
のYOUR_MAPBOX_ACCESS_TOKEN
の部分をご自身のパブリックトークンに変更してください。
レイアウト
レイアウトは「最も簡単なコード」と同じでOKです。
コード
地図のスタイルのカスタマイズ
地図のスタイルに関する変更はcustomizeViewOptions
で行います。ここでは地図のスタイルを「Mapbox Satellite Streets」、経路の色を以下に変更しています。
- 渋滞情報がない場合はマゼンタ
- 渋滞が少ない場合はシアン
- Casing(経路の外側の線)は赤
binding.navigationView.customizeViewOptions {
mapStyleUriDay = Style.SATELLITE_STREETS
routeLineOptions = MapboxRouteLineOptions.Builder(applicationContext)
.withRouteLineResources(
RouteLineResources.Builder()
.routeLineColorResources(
RouteLineColorResources.Builder()
.routeLowCongestionColor(Color.CYAN)
.routeUnknownCongestionColor(Color.MAGENTA)
.routeCasingColor(Color.RED)
.build()
)
.build()
)
.build()
}
ナビゲーションで表示しているUIのカスタマイズ
ナビゲーションで表示しているUIの色やアイコンの変更はcustomizeViewStyles
で行います。ここでは「ナビゲーションを開始するボタン」のアイコンを変更しています。具体的には以下の場所です。
まずdrawable
以下にアイコンファイルを保存します。ここでは以下のICOOON MONO様のラーメンのアイコン(ramen.png)を使用しました。
CustomizedDropinUi/app/src/main/res/values/styles.xml
で以下のようにアイコンを設定します.
<style name="CustomStartNavigationButtonStyle">
<item name="extendableButtonIcon">@drawable/ramen</item>
</style>
次に以下のようにスタイルを設定します。
binding.navigationView.customizeViewStyles {
startNavigationButtonStyle = R.style.MyStartNavigationButtonStyle
}
独自のUIをナビゲーションに使用する
独自のUIをナビゲーションに使用するにはcustomizeViewBinders
を使用します。ここでは進捗を示す下側に出ているUIを変更していきます。
まず、表示したいUIのレイアウトを作成します。ここではcustom_trip_progress.xml
というファイルを作成し、以下のように定義しました。中身はTextView
一つだけです。
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:parentTag="android.widget.FrameLayout">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/tripProgressView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="8dp"
android:paddingStart="8dp">
<TextView
android:id="@+id/messageTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="32sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="message here" />
</androidx.constraintlayout.widget.ConstraintLayout>
</merge>
次にこのレイアウトを親UIに紐付けるクラスを作成します。
class CustomTripProgressViewBinder : UIBinder {
override fun bind(viewGroup: ViewGroup): MapboxNavigationObserver {
val scene = Scene.getSceneForLayout(
viewGroup,
R.layout.custom_trip_progress,
viewGroup.context
)
TransitionManager.go(scene, Fade())
val binding = CustomTripProgressBinding.bind(viewGroup)
return CustomTripProgressComponent(binding)
}
}
さらに、CustomTripProgressViewBinder
の中身を描画するクラスを定義します。ここでは進捗が80%未満であればTextView
に「まだだよ」と表示し、それ以上であれば「もうすぐだよ」と表示します。
class CustomTripProgressComponent(private val binding: CustomTripProgressBinding) : UIComponent() {
override fun onAttached(mapboxNavigation: MapboxNavigation) {
super.onAttached(mapboxNavigation)
coroutineScope.launch {
mapboxNavigation.flowRouteProgress().collect {
val ratio = it.distanceTraveled / (it.distanceTraveled + it.distanceRemaining)
binding.messageTextView.text = when {
ratio < 0.8 -> "まだまだだよ"
else -> "もうすぐだよ"
}
}
}
}
}
最後にcustomizeViewBinders
を用いてCustomTripProgressViewBinder
を登録します。
binding.navigationView.customizeViewBinders {
infoPanelTripProgressBinder = CustomTripProgressViewBinder()
}
結果
まとめ
NavigationView
を使用すると、コードを書くことなくナビゲーションアプリケーションが作成できます。また、スタイルやUIも柔軟にカスタマイズできます。
Discussion