はじめに
この記事はFlutter Advent Calendar 2018の6日目分です。
すぐに枠が埋まってしまっていたのでFlutter Advent Calendarに参加する予定はなかったのですが、ふとカレンダーを覗いていみると6日枠が投稿されずに空いていたので急遽この記事を書くことにしました。
Flutterの最新情報に興味がある方はFlutterウィークリーもよかったらご覧ください
https://qiita.com/tags/flutterweekly
Google公式Flutter用Google Mapsプラグインがついに公開
Flutterユーザーならみなさんご存知かと思いますがFlutter上でGoogle Mapsを使う公式プラグインは存在しませんでした。
ところが先日「Flutterウィークリー #37」でもお伝えしたとおり、Googleから公式のGoogle Mapsプラグインが公開されました。現在はデベロッパープレビューという形で提供されていますが、誰でも利用することが出来ます。
以前に
FlutterでインラインMapViewを作ってみた(サンプルコード付き)
https://qiita.com/aoinakanishi/items/35bef7de85fdee46bef9
の記事でOpen Street Mapのデータを使ってMapViewを自作しましたが、公式のGoogle Mapsプラグインがあればもう不要ですね。
パッケージ
google_maps_flutterのGithubリポジトリ
APIキーの取得
https://cloud.google.com/maps-platform/
からGoogle Maps用のAPIキーを取得します
既存のプロジェクトを選択するか新たにプロジェクトを追加してNEXTをクリック
ポチポチクリックしていくと以下のような画面が出てAPIキーの準備が整いました
dependencyにgoogle_maps_flutterを追加
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
google_maps_flutter: ^0.0.3+3
dev_dependencies:
flutter_test:
sdk: flutter
Android用設定
android/app/src/main/AndroidManifest.xmlを開き以下の通りcom.google.android.geo.API_KEYを追加
APIキーは先に発行したものに置き換えてください
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_google_maps"
android:icon="@mipmap/ic_launcher">
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789a_b"/>
<activity
...
iOS用設定
ios/Runner/Info.plistを開いて以下を追記します
<key>io.flutter.embedded_views_preview</key>
<string>YES</string>
次にios/Runner/AppDelegate.swiftを開き、「import GoogleMaps」と「GMSServices.provideAPIKeyの行」を追加
GoogleのサンプルだとObjective-Cが例として出ていますが、こちらはSwiftになります。 Flutter公式プラグインにPR出してmergeされたました
https://github.com/flutter/plugins/pull/1161
import UIKit
import Flutter
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789a_b")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
共通部分のFlutterコード
Android, iOSの個別の設定が終わったらFlutterのコードを書きます
パッケージの宣言
import 'package:google_maps_flutter/google_maps_flutter.dart';
GoogleMap表示部分
GoogleMap(
onMapCreated: (GoogleMapController controller) {},
),
main.dart全部(コピペで動きます)
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Flutter Google Maps')),
body: MapsDemo(),
),
));
}
class MapsDemo extends StatefulWidget {
@override
State createState() => MapsDemoState();
}
class MapsDemoState extends State<MapsDemo> {
GoogleMapController mapController;
@override
Widget build(BuildContext context) {
return Scaffold(
// ここを追加
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
onMapCreated: _onMapCreated,
),
),
);
}
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
});
}
}
スクリーンショット
Android
iOS
Googleの提供するサンプルはここまでですが、プラグインのコードを見るといろいろと機能が実装されていますので触っていきましょう
最新バージョンのGoogleMapsプラグインを使う
2018/12/10時点の記事執筆時点ではPubに最新版(0.1.0)のGoogleMapsプラグインが提供されていないため、最新版のプラグインを使用する場合はこちらの作業が必要です。
Google公式のプラグインをclone
git clone git@github.com:flutter/plugins.git
pubspec.yamlに以下を追加
dev_dependencies:
flutter_test:
sdk: flutter
google_maps_flutter:
path: ../plugins/packages/google_maps_flutter/
../plugins
は上でgit cloneしてきたディレクトリ
※flutter packages upgrade
ではIDE(Android Studio)が読み込んでいるプラグインをプラグインを切り替えることが出来ないので一度プロジェクトを閉じてから開き直す
Google Mapの動きを制御
GoogleMapのonMapCreatedコールバック時にGoogleMapControllerを使って地図を制御します。
表示位置(カメラ位置)を変更
この例ではonMapCreated時にGoogleMapControllerを使ってカメラ位置を移動しています。
アニメーションさせずに移動する場合はanimateCamera
の代わりにmoveCamera
を使用します
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
mapController.animateCamera(CameraUpdate.newCameraPosition(
const CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
));
});
}
必須 | 初期値 | ||
---|---|---|---|
target | ✓ | LatLngで緯度経度を指定 | |
bearing | 0.0 | 方向 | |
tilt | 0.0 | 角度 | |
zoom | 0.0 | ズームレベル |
初期表示位置(カメラ位置)を変更 (バージョン0.1.0以上)
initialCameraPosition
にCameraPositionを指定
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
)
),
現在地ボタンを表示
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
myLocationEnabled: true,
),
地図タイプを変更
サテライトマップ
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.satellite
),
地形マップ
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.terrain
),
ハイブリットマップ
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.hybrid
),
地図表示なし
独自地図を描画したい場合でGoogleMapsの他のAPIを使用したい場合などに使用します
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.none
),
地図のズームレベル(最小と最大)を制御
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
minMaxZoomPreference: MinMaxZoomPreference(16, 18)
),
カメラが移動できる範囲を指定
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
cameraTargetBounds: CameraTargetBounds(
LatLngBounds(
southwest: LatLng(35.6483486,139.6928292),
northeast: LatLng(35.6684576,139.7102434),
)
)
),
その他のパラメーター
GoogleMapクラスの初期化時に指定出来るパラメータ一覧
デフォルト値 | 説明 | |
---|---|---|
onMapCreated | Mapが生成された時のコールバック | |
gestureRecognizers | ListView上に地図を表示するなど、Map上で使用可能なジェスチャーを制御したい場合に使用 | |
compassEnabled | true | マップ回転時にコンパスを表示 |
cameraTargetBounds | CameraTargetBounds.unbounded | カメラが移動できる範囲を指定(前述のサンプル参照) |
mapType | MapType.normal | 地図タイプ(前述のサンプル参照) |
minMaxZoomPreference | MinMaxZoomPreference.unbounded | ズームレベルの最小、最大値を指定(前述のサンプル参照) |
rotateGesturesEnabled | true | 地図の回転を許可 |
scrollGesturesEnabled | true | 地図の移動を許可 |
zoomGesturesEnabled | true | 地図のズームを許可 |
tiltGesturesEnabled | true | 地図の傾きを許可 |
trackCameraPosition | false | カメラ移動イベントをFlutterに通知 |
myLocationEnabled | false | 現在地表示ボタンの表示 |
地図上にマーカーを表示
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
var options = MarkerOptions(
position: LatLng(35.6580339,139.7016358)
);
mapController.addMarker(options);
});
マーカーに吹き出し(情報ウィンドウ)にテキスト表示
マーカーをタップすると吹き出しが表示されます
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
var options = MarkerOptions(
position: LatLng(35.6580339,139.7016358),
infoWindowText: InfoWindowText("タイトル", "説明分等")
);
mapController.addMarker(options);
});
マーカーの色を変更
var options = MarkerOptions(
position: LatLng(35.6580339,139.7016358),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen)
);
mapController.addMarker(options);
Hueには0.0から360.0まで指定可能
定義済みの色は以下の通り
値 | |
---|---|
BitmapDescriptor.hueRed | 0.0 |
BitmapDescriptor.hueOrange | 30.0 |
BitmapDescriptor.hueYellow | 60.0 |
BitmapDescriptor.hueGreen | 120.0 |
BitmapDescriptor.hueCyan | 180.0 |
BitmapDescriptor.hueAzure | 210.0 |
BitmapDescriptor.hueBlue | 240.0 |
BitmapDescriptor.hueViolet | 270.0 |
BitmapDescriptor.hueMagenta | 300.0 |
BitmapDescriptor.hueRose | 330.0 |
マーカーの画像を変更
pubspec.yamlにリソースを追加
assets:
# http://www.iconarchive.com/show/merry-christmas-icons-by-lovuhemant/Santa-icon.html
- res/images/santa.png
main.dart
var options = MarkerOptions(
position: LatLng(35.6580339,139.7016358),
icon: BitmapDescriptor.fromAsset("res/images/santa.png")
);
mapController.addMarker(options);
その他のマーカーオプション
初期値 | 説明 | |
---|---|---|
alpha | 1.0 | マーカーの透過度 |
anchor | Offset(0.5, 1.0) | マーカー画像の表示オフセット |
consumeTapEvents | false | マーカータップイベントを取得(未実装) |
draggable | false | マーカーの移動を許可 |
flat | false | フラットに描画(地図の角度を変更した際に挙動が異なる) |
icon | BitmapDescriptor.defaultMarker | マーカーとして表示する画像 |
infoWindowAnchor | Offset(0.5, 0.0) | 吹き出しの表示オフセット |
infoWindowText | InfoWindowText.noText | 吹き出しの表示内容(前述のサンプル参照) |
position | LatLng(0.0, 0.0) | マーカー表示位置 |
rotation | 0.0 | マーカーの回転(時計回り) |
visible | true | 表示 |
zIndex | 0.0 | マーカーのZ軸を指定(重なる時にどちらを手前に出すか) |
※consumeTapEvents
については、Issueにも上がっている通り、未実装で現時点では使用することが出来ません
https://github.com/flutter/flutter/issues/25039
まとめ
google_maps_flutter
のコードを読みながら一通りの操作をしてみました。地図やマーカーの描画、付随する情報の表示であれば問題なく動作します。
各種イベントを取得して操作をする事ができない。オーバーレイやPolylineの描画も出来ません。スタイルの変更やGeoJSONなど、Google Maps APIを使った少し複雑なことが出来ない。など、デベロッパープレビューとして公開されたばかりのバージョン0.1.0なので出来ないことのほうが多いですが、今後に期待ですね。
この記事のソースコード