Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

この記事は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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした