質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

1回答

587閲覧

【Flutter】GoogleMapのダークモード、ライトモードをリアルタイムに反映させたいのですができません。

bbiiq

総合スコア51

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

0グッド

0クリップ

投稿2023/05/23 05:41

質問内容

FlutterでGoogleMapを表示させているのですが、デバイスの設定の外観モードを変更すると、GoogleMapの外観を変えたいです。
しかし、GoogleMapの「onMapCreated」プロパティが実行されません。
どうすれば、アプリがバックグラウンドから戻ってきたタイミングでGoogleMapの外観を変更させることができるのでしょうか?

該当のソースコード

Dart

1import 'dart:async'; 2import 'dart:ui' as ui; 3 4import 'package:flutter/material.dart'; 5import 'package:google_maps_flutter/google_maps_flutter.dart'; 6import 'package:flutter/services.dart' show rootBundle; 7 8void main() => runApp(const MyApp()); 9 10class MyApp extends StatelessWidget { 11 const MyApp({super.key}); 12 13 Widget build(BuildContext context) { 14 return const MaterialApp( 15 home: MapSample(), 16 ); 17 } 18} 19 20class MapSample extends StatefulWidget { 21 const MapSample({super.key}); 22 23 State<MapSample> createState() => MapSampleState(); 24} 25 26class MapSampleState extends State<MapSample> with WidgetsBindingObserver { 27 final Completer<GoogleMapController> _controller = Completer(); 28 late Brightness justBeforeMode; 29 30 31 void initState() { 32 super.initState(); 33 WidgetsBinding.instance.addObserver(this); 34 } 35 36 37 void dispose() { 38 WidgetsBinding.instance.removeObserver(this); 39 super.dispose(); 40 } 41 42 43 void didChangeAppLifecycleState(AppLifecycleState state) { 44 super.didChangeAppLifecycleState(state); 45 if (AppLifecycleState.paused == state) { 46 justBeforeMode = ui.window.platformBrightness; 47 } 48 if (AppLifecycleState.resumed == state) { 49 if (ui.window.platformBrightness != justBeforeMode) { 50 setState(() {}); 51 } 52 } 53 } 54 55 56 Widget build(BuildContext context) { 57 return Scaffold( 58 body: ui.window.platformBrightness == Brightness.light 59 ? 60 // lightMode 61 GoogleMap( 62 mapType: MapType.normal, 63 initialCameraPosition: const CameraPosition( 64 target: LatLng(37.42796133580664, -122.085749655962), 65 ), 66 onMapCreated: (GoogleMapController controller) async { 67 _controller.complete(controller); 68 }, 69 ) 70 : 71 // darkMode 72 GoogleMap( 73 mapType: MapType.normal, 74 initialCameraPosition: const CameraPosition( 75 target: LatLng(37.42796133580664, -122.085749655962), 76 ), 77 onMapCreated: (GoogleMapController controller) async { 78 final darkGoogleMapStyle = await rootBundle 79 .loadString('assets/jsons/dark_map_style.json'); 80 await controller.setMapStyle(darkGoogleMapStyle); 81 _controller.complete(controller); 82 }, 83 ), 84 ); 85 } 86} 87

補足情報(FW/ツールのバージョンなど)

[✓] Flutter (Channel stable, 3.7.10, on macOS 13.3.1)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
[✓] Android Studio (version 2021.3)
[✓] VS Code (version 1.73.0)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

MapSampleState側だけ。

dart

1class MapSampleState extends State<MapSample> with WidgetsBindingObserver { 2 GoogleMapController? _controller; 3 final String _light = "[]"; 4 late String _dark; 5 6 7 void initState() { 8 rootBundle 9 .loadString('assets/jsons/dark_map_style.json') 10 .then((value) => _dark = value); 11 super.initState(); 12 WidgetsBinding.instance.addObserver(this); 13 } 14 15 void _setMapStyle() { 16 _controller?.setMapStyle( 17 PlatformDispatcher.instance.platformBrightness == Brightness.light 18 ? _light 19 : _dark); 20 } 21 22 23 void dispose() { 24 WidgetsBinding.instance.removeObserver(this); 25 super.dispose(); 26 } 27 28 29 void didChangePlatformBrightness() { 30 _setMapStyle(); 31 } 32 33 34 Widget build(BuildContext context) { 35 return Scaffold( 36 body: GoogleMap( 37 mapType: MapType.normal, 38 initialCameraPosition: const CameraPosition( 39 target: LatLng(37.42796133580664, -122.085749655962), 40 ), 41 onMapCreated: (GoogleMapController controller) { 42 _controller = controller; 43 _setMapStyle(); 44 }, 45 ), 46 ); 47 } 48}

私のコードではスタイルの変更タイミングは、didChangePlatformBrightnessが来た時に行っている。
提示されているコードではAppLifecycleState.resumedだけど、didChangePlatformBrightnessの方が正しいと思う。

本題のスタイル変更の処理に関しては、GoogleMapControllerに対してsetMapStyleを適用するというのが正しいのだけど、それを行う場所はonMapCreatedの中でというわけではなく、GoogleMapControllerが確定しているのであればどこでも実行可能。
そのため、onMapCreatedで確定後とそれを_controllerに入れた後であればどこでもアクセスはできる。
そういうことでdidChangePlatformBrightnessの中で現在の輝度モードの設定によりスタイルを変更する処理を走らせることでスタイルの更新ができるようになる。
Androidで試したけどiOSでもたぶん同じだと思う(思いたい)。

提示された実装ではbuildメソッド内でui.window.platformBrightness == Brightness.lightで構築するウィジェットを切り替えようとしているけど、これは生成されるウィジェットは同一と判断されるので、State側は再構築されずonMapCreatedは呼び出されないのでスタイルの変更は行われないという状況になっている。


実装を一部修正。
Completerを使っていた部分をnull許容変数に変更。
google_maps_flutterのトップページにあるサンプルではCompleterを使っているのだけど、github側の例はほとんどが?のnull許容変数を使っていたのと、このような使い方でCompleterは適当ではないと思い変更しました。

投稿2023/05/24 03:12

編集2023/05/24 09:05
ta.fu

総合スコア1676

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bbiiq

2023/05/24 03:37

回答ありがとうございます。 教えていただいたコードでうまくいきました。 とても勉強になりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問