Flutter×GoogleMap基礎編⑤〜ダークモード切替ボタンを作る

プログラミング

はじめに

FlutterアプリケーションにGoogleMapを組み込むためのパッケージである
google_maps_flutterの使い方をご紹介します。

前回の基礎編④では、GoogleMap()ウィジェットに対する
タップイベントを検知してマップを更新する方法をご紹介しました。

しかし、GoogleMap()ウィジェットに対するイベントではなく、
ボタンを押した時にGoogleMap()に何らかの操作をしたい時があるかと思います。
そういった場合には今回紹介するコントローラを使った方法をとります

今回の基礎編⑤では、コントローラからGoogleMap()ウィジェットをダークモードに切り替える
方法を例としてご紹介します。

基礎編①〜④をご覧になりたい方は下記からご参照ください。

https://kentosjpn.com/programming/14/
https://kentosjpn.com/programming/15/
https://kentosjpn.com/programming/16/
https://kentosjpn.com/programming/17/

実装していく

今回使用するgoogle_maps_flutterのバージョンは下記です。

dependencies:
  google_maps_flutter: ^2.1.4

 

コントローラを生成する

まずはマップを操作するためのコントローラを取得します。
サンプルコードをコピペして実行してください。

そうするとこれまでと同様GoogleMapと右下にボタンが表示されるかと思います。
このボタンを押すとダークモードに切り替えるように実装します。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() {
  runApp(MaterialApp(home: Map()));
}

class Map extends StatefulWidget {
  const Map({Key? key}) : super(key: key);
  @override
  State<Map> createState() => _MapState();
}

class _MapState extends State<Map> {
  Completer<GoogleMapController> _controller = Completer();// コントローラのCompleterを定義

  static final CameraPosition _cameraPosition =
      CameraPosition(target: LatLng(35, 135), zoom: 15);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        myLocationButtonEnabled: false,
        initialCameraPosition: _cameraPosition,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller); // コントローラの生成が終わったことを知らせる。
        },
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () async {},
        label: Text('change mode'),
      ),
    );
  }
}
  • onMapCreated()メソッド
    GoogleMap()ウィジェットの生成が完了したら呼ばれるメソッドです。
    コールバックとしてコントローラが生成されますので、そちらを使ってマップを操作していきます。
  • GoogleMapController
    GogleMap()ウィジェットを操作するためのコントローラです。
    16行目で定義しているCompleter<GoogleMapController>型_controller変数に格納しています。
    Completerについては詳細に解説しませんが、Completer<T>はT型のオブジェクトの確定に責任を持ちます。つまり今回はCompleter<GoogleMapController>型なので、.complete(controller)とした時にGoogleMapControllerオブジェクトが確定したことを知らせます。(確定されたものは後ほどFuture型として参照します。)

なぜCompleterを使うの?
コントローラの生成(GoogleMapウィジェットの生成)が完了する前に別の処理がコントローラを参照することを防止するためです。

コントローラからマップスタイルを変更する

 // マップスタイルを変更する関数を定義
  Future<void> _changeMapStyle() async {
    final GoogleMapController controller = await _controller.future;
    controller.setMapStyle(style); // マップスタイルをコントローラに引き渡す
  }

// ボタンのonPressedメソッドから呼び出す
 floatingActionButton: FloatingActionButton.extended(
        onPressed: () {
          _changeMapStyle(); // 追加
        },
        label: Text('change mode'),
      ),
  • _changeMapStyle()メソッド
    自作関数です。ボタンが押された時の処理を記述します。
    _controller.futureCompleterによって確定されたコントローラを参照します。
    戻り値はFuture型のため、awaitで待ちます。
  • controller.setMapStyle()メソッド
    引数で指定したスタイルにマップを切り替えます。
    styleはString型の変数ですが、JSONにデコード可能な形式である必要があります。
    長いですが、下記を定数として定義しておいてください。
//String型だけど中身はJSON形式
static const style = ''' [ { "elementType": "geometry", "stylers": [ { "color": "#242f3e" } ] }, { "elementType": "labels.text.fill", "stylers": [ { "color": "#746855" } ] }, { "elementType": "labels.text.stroke", "stylers": [ { "color": "#242f3e" } ] }, { "featureType": "administrative.locality", "elementType": "labels.text.fill", "stylers": [ { "color": "#d59563" } ] }, { "featureType": "poi", "elementType": "labels.text.fill", "stylers": [ { "color": "#d59563" } ] }, { "featureType": "poi.park", "elementType": "geometry", "stylers": [ { "color": "#263c3f" } ] }, { "featureType": "poi.park", "elementType": "labels.text.fill", "stylers": [ { "color": "#6b9a76" } ] }, { "featureType": "road", "elementType": "geometry", "stylers": [ { "color": "#38414e" } ] }, { "featureType": "road", "elementType": "geometry.stroke", "stylers": [ { "color": "#212a37" } ] }, { "featureType": "road", "elementType": "labels.text.fill", "stylers": [ { "color": "#9ca5b3" } ] }, { "featureType": "road.highway", "elementType": "geometry", "stylers": [ { "color": "#746855" } ] }, { "featureType": "road.highway", "elementType": "geometry.stroke", "stylers": [ { "color": "#1f2835" } ] }, { "featureType": "road.highway", "elementType": "labels.text.fill", "stylers": [ { "color": "#f3d19c" } ] }, { "featureType": "transit", "elementType": "geometry", "stylers": [ { "color": "#2f3948" } ] }, { "featureType": "transit.station", "elementType": "labels.text.fill", "stylers": [ { "color": "#d59563" } ] }, { "featureType": "water", "elementType": "geometry", "stylers": [ { "color": "#17263c" } ] }, { "featureType": "water", "elementType": "labels.text.fill", "stylers": [ { "color": "#515c6d" } ] }, { "featureType": "water", "elementType": "labels.text.stroke", "stylers": [ { "color": "#17263c" } ] } ] ''';

オリジナルスタイルに変更する

マップのスタイルはJSONの値を変更すればオリジナルのスタイルで表示することができます。
下記サイトで好きにカスタムしたスタイルをJSON形式で出力することがきて便利です。

https://mapstyle.withgoogle.com/

おわりに

5回にわたってご紹介してきたgoogle_maps_flutterパッケージの使い方はいかがでしたでしょうか。
私の記事が皆さんのアプリ制作の一助になれば幸いです。

コメント

タイトルとURLをコピーしました