Edited at
FlutterDay 6

Google公式Flutter用Google Mapsプラグインを一通り使ってみた


はじめに

この記事は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プラグインがあればもう不要ですね。


パッケージ

https://pub.dartlang.org/packages/google_maps_flutter


google_maps_flutterのGithubリポジトリ

https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter


APIキーの取得

https://cloud.google.com/maps-platform/

からGoogle Maps用のAPIキーを取得します

↑を開いて「使ってみる」をクリック

Screen Shot 2018-12-08 at 15.28.45.png

「Maps」を選んでCONTINUEをクリック

Screen Shot 2018-12-08 at 15.29.00.png

既存のプロジェクトを選択するか新たにプロジェクトを追加してNEXTをクリック

Screen Shot 2018-12-08 at 15.30.53.png

ポチポチクリックしていくと以下のような画面が出てAPIキーの準備が整いました

Screen Shot 2018-12-08 at 15.36.32.png


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されたました:tada:

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

Screen Shot 2018-12-08 at 16.05.51.png


iOS

Screen Shot 2018-12-08 at 16.02.27.png

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
ズームレベル

Screen Shot 2018-12-10 at 05.16.05.png


初期表示位置(カメラ位置)を変更 (バージョン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,
),

Screen Shot 2018-12-10 at 05.16.33.png


地図タイプを変更


サテライトマップ

        child: GoogleMap(

onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.satellite
),

Screen Shot 2018-12-10 at 05.16.45.png


地形マップ

        child: GoogleMap(

onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.terrain
),

Screen Shot 2018-12-10 at 05.16.52.png


ハイブリットマップ

        child: GoogleMap(

onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.hybrid
),

Screen Shot 2018-12-10 at 05.17.02.png


地図表示なし

独自地図を描画したい場合でGoogleMapsの他のAPIを使用したい場合などに使用します

        child: GoogleMap(

onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(35.6580339,139.7016358),
zoom: 17.0,
),
mapType: MapType.none
),

Screen Shot 2018-12-10 at 05.17.09.png


地図のズームレベル(最小と最大)を制御

        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);
});

Screen Shot 2018-12-10 at 06.16.04.png


マーカーに吹き出し(情報ウィンドウ)にテキスト表示

マーカーをタップすると吹き出しが表示されます

  void _onMapCreated(GoogleMapController controller) {

setState(() {
mapController = controller;
var options = MarkerOptions(
position: LatLng(35.6580339,139.7016358),
infoWindowText: InfoWindowText("タイトル", "説明分等")
);
mapController.addMarker(options);
});

Screen Shot 2018-12-10 at 06.20.42.png


マーカーの色を変更

      var options = MarkerOptions(

position: LatLng(35.6580339,139.7016358),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen)
);
mapController.addMarker(options);

Hueには0.0から360.0まで指定可能

Screen Shot 2018-12-10 at 06.26.56.png

定義済みの色は以下の通り

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);

Screen Shot 2018-12-10 at 06.36.59.png


その他のマーカーオプション

初期値
説明

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なので出来ないことのほうが多いですが、今後に期待ですね。


この記事のソースコード

https://github.com/aoinakanishi/flutter-google-maps-example