Toto je blogový článek představující funkce použitelné při vývoji mapových aplikací ve Flutteru v sérii.Funkce zobrazování mapy synchronizované s aktuální polohou zařízení je běžně diskutovaná v mobilních mapových aplikacích. V tomto článku představíme, jak tuto funkci implementovat pomocí mapového SDK pro Flutter (ArcGIS Maps SDK for Flutter).
Ukázkový kód je zveřejněn na GitHubu, takže pokud chcete ihned zkontrolovat, stáhněte si ho. Návod k spuštění aplikace najdete v README. Pro spuštění ukázky je potřeba získat API klíč (zdarma).
Postup od zavedení mapového SDK až po zobrazení mapy najdete v blogovém článku „Flutter – Vytvořme si mapovou aplikaci!“. Tento článek se zaměřuje na funkci zobrazení mapy synchronizované s aktuální polohou.
Přidání oprávnění
Pro přístup k poloze zařízení v aplikaci je nutné přidat následující oprávnění. Přidejte příslušná oprávnění do odpovídajících souborů.
Android
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
iOS
ios/Runner/Info.plist
<key>NSLocationUsageDescription</key>
<string>Pro přístup k poloze je třeba povolení využití polohy v aplikaci.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Pro přístup k poloze je třeba povolení využití polohy v aplikaci.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Pro přístup k poloze je třeba povolení využití polohy v aplikaci.</string>
Řetězec nastavený v tagu string v Info.plist se zobrazí uživateli jako potvrzovací zpráva při přístupu k poloze. Nastavte libovolnou zprávu dle potřeby.
Implementace funkce zobrazení aktuální polohy
Funkce zobrazení aktuální polohy na mapě používá třídu LocationDisplay クラスを使用します。LocationDisplay は LocationDataSource で指定したデータソースから現在地を取得し、マップ上に現在地のシンボルを表示します。現在地が更新されると、マップ上のシンボルの位置も自動で更新されます。また、現在地、方位、進行方向が更新されたときにマップを自動的に移動や回転させることもできます。
1. 「Flutter で地図アプリを作成してみよう!」のブログ記事の手順 6 で、マップビュー コントローラーに作成したマップを設定してマップの表示までできたら、_mapViewController の LocationDisplay に位置情報のソースとなるデータ ソースを設定します。
・・・
// マップビュー コントローラーに作成したマップを設定します。
_mapViewController.arcGISMap = map;
// 追加
// システムの位置情報サービスの現在位置をマップ上に表示するように設定します。
_mapViewController.locationDisplay.dataSource = SystemLocationDataSource();
データ ソースには、SystemLocationDataSource と SimulatedLocationDataSource を設定できます。SystemLocationDataSource はデバイス システムで使用される位置情報を使用します。SimulatedLocationDataSource はテスト用にシミュレートされたデバイスの位置情報を使用できます。現在地 (ArcGISLocation) のコレクションを使用するか、setLocationsWithPolyline メソッドで移動速度とラインを指定して、ラインに沿って現在地を移動させることもできます。
2. 続いて、位置情報が更新されたときにマップをどのように表示/移動させるかを AutoPanMode を使用して設定します。
// AutoPanMode を Recenter モードに設定します。
_mapViewController.locationDisplay.autoPanMode = LocationDisplayAutoPanMode.recenter;
AutoPanMode は、徒歩や車両でのナビゲーション用に以下の表示モードが用意されています。アプリの用途に応じて適切なモードを選択/切替えて利用できます。
- Recenter: 現在地が wanderExtentFactor で設定された範囲外に移動したときに、現在地を再度画面の中心に表示するようにマップが自動で移動します。wanderExtentFactor には、0 から 1 の間の値を設定します。0 の場合は、現在地が更新される度にマップが移動します。1 の場合は、現在地が現在のマップの表示範囲の端に達したときにマップが移動します。
- Navigation: 現在地が常に画面の下部に表示されるようにマップが自動で移動します。また、進行方向が常にデバイス上端を向くように、進行方向に基づいて自動でマップが回転します。車両での移動を想定したモードです。
- Compass Navigation: 現在地が常に画面の中心に表示されるようにマップが自動で移動します。また、向いている方向が常にデバイス上端を向くように、向きに基づいて自動でマップが回転します。徒歩での移動を想定したモードです。
- Off: 現在地のみが更新され、地図は自動で移動しません。
3. 位置情報の取得を開始するための準備ができたので LocationDisplay の start メソッドを呼び出します。
// 位置情報の取得を開始します(これにより、ユーザーに許可を求めるプロンプトが表示されます)。
try {
await _mapViewController.locationDisplay.dataSource.start();
} on ArcGISException catch (e) {
if (mounted) {
showDialog(
context: context,
builder: (_) => AlertDialog(content: Text(e.message)),
);
}
}
非同期に関するエラーが発生したら、_onMapViewReady 関数に async を付けて、下記のように変更します。
Future<void> _onMapViewReady() async {
これで、デバイスが現在地を取得できる場合に、現在地を示す青いシンボルがマップの中心に表示されるはずです。
4. 続いて、位置情報の取得の開始/停止と AutoPanMode を切り替える UI を実装します。まず、これらの UI を含む locationSettings ウィジェットを作成します。
Widget locationSettings(BuildContext context) {
return Container(
padding: EdgeInsets.fromLTRB(
20.0,
20.0,
20.0,
max(
20.0,
View.of(context).viewPadding.bottom / View.of(context).devicePixelRatio,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Text(
'表示設定',
style: Theme.of(context).textTheme.titleLarge,
),
const Spacer(),
],
),
Row(
children: [
const Text('ロケーションの表示'),
const Spacer(),
// 位置情報の取得を開始および停止するためのスイッチです。
Switch(
value: _isLocationStarted,
onChanged: (value) {
setState(() {
if (_mapViewController.locationDisplay.dataSource.status == LocationDataSourceStatus.started) {
_mapViewController.locationDisplay.stop();
_isLocationStarted = false;
} else {
_mapViewController.locationDisplay.start();
_isLocationStarted = true;
}
});
},
),
],
),
Row(
children: [
const Text('Auto-Pan モード'),
const Spacer(),
// AutoPanMode を選択するためのドロップダウン ボタンです。
DropdownButton(
value: _mapViewController.locationDisplay.autoPanMode,
onChanged: (value) {
setState(() {
_mapViewController.locationDisplay.autoPanMode = value!;
});
},
items: const [
DropdownMenuItem(
value: LocationDisplayAutoPanMode.off,
child: Text('Off'), // 現在位置のシンボルをマップ上に表示するのみ
),
DropdownMenuItem(
value: LocationDisplayAutoPanMode.recenter,
child: Text('Znovu vycentrovat'), // Přiblíží mapu tak, aby byla aktuální poloha uprostřed
),
DropdownMenuItem(
value: LocationDisplayAutoPanMode.navigation,
child: Text(
'Navigace'), // Zobrazuje aktuální polohu vždy ve spodní části mapy a otáčí mapu podle směru pohybu zařízení
),
DropdownMenuItem(
value: LocationDisplayAutoPanMode.compassNavigation,
child: Text(
'Compass'), // Zobrazuje aktuální polohu vždy uprostřed mapy a otáčí mapu podle směru, kterým zařízení směřuje
),
],
),
],
),
],
),
);
}
5. Přidejte widget locationSettings vytvořený v předchozím kroku do Expanded, který obsahuje ArcGISMapView.
children: [
Expanded(
// Přidání mapového zobrazení do stromu widgetů a nastavení kontroléru.
child: ArcGISMapView(
controllerProvider: () => _mapViewController,
onMapViewReady: _onMapViewReady,
),
),
// Přidání widgetu locationSettings pod mapové zobrazení.
locationSettings(context),
],
6. Na začátku třídy _MyHomePageState vytvořte proměnnou _isLocationStarted pro sledování stavu LocationDisplay. Ve widgetu locationSettings zapněte přepínač „Zobrazit polohu“, když se LocationDisplay spustí (start) a vypněte jej, když se LocationDisplay zastaví (stop).
bool _isLocationStarted = true;
7. Nakonec otevřete lib/main.dart a za již existující importy přidejte následující kód pro import potřebných balíčků.
import 'dart:math';
Tím je uživatelské rozhraní pro spuštění/zastavení získávání polohy a přepínání AutoPanMode hotové. Spusťte aplikaci a vyzkoušejte přepínání režimů AutoPanMode, abyste viděli chování jednotlivých režimů.
Shrnutí
V tomto článku jsme implementovali funkci zobrazování mapy synchronizované s aktuální polohou zařízení. Třída LocationDisplay umožňuje také další nastavení, která zde nebyla zmíněna, jako změna symbolu aktuální polohy, měřítko mapy při počátečním zobrazení nebo pozice zobrazení v režimu Navigace. Určitě si vyzkoušejte vlastní styl zobrazení a přizpůsobení.
Související odkazy