I'm working on an flutter application that should have a common codebase for web and mobile.
My app will have a google map and as far as I've seen there's not a single package to satisfy all platforms.
google_maps_flutter - seems to work only for mobile (IOS / Android)
google_maps_flutter_web - seems to work only for web
So most probably I have to create two separate MapWidgets, one for the web and one for mobile using these separate packages.
For mobile:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapSample extends StatefulWidget {
MapSample({Key? key}) : super(key: key);
@override
State<MapSample> createState() => MapSampleState();
}
class MapSampleState extends State<MapSample> {
final Completer<GoogleMapController> _controller = Completer();
static const CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
@override
Widget build(BuildContext context) {
return GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
);
}
}
For the web, it's a bit more complicated, it seems that google_maps_flutter_web
isn't actually an usable version, from what I understand, (correct me if I'm wrong) and it actually uses another package that's not developed by the flutter team google_maps 6.0.0
.
The objective of google_maps_flutter_web
probably is to have the same api as google_maps_flutter
(google_maps_flutter_platform_interface
) and use it seamlessly, but I couldn't really find an example of how to use it...
How should I go about this? Any change I'm mistaken about google_maps_flutter_web and it actually works? Or I should just try to use google_maps
which actually works for the web and just switch widgets based on kIsWeb
?
CodePudding user response:
Eventually I found a workaround using google_maps
and this answer as inspiration:
- Abstract MapWidget
import 'package:client_ojp4danube/map/map_widget_stub.dart'
if (dart.library.html) 'package:client_ojp4danube/map/map_web_widget.dart'
if (dart.library.io) 'package:client_ojp4danube/map/map_widget.dart';
import 'package:flutter/material.dart';
abstract class MapWidget extends StatefulWidget {
factory MapWidget() => getMapWidget();
}
- WebMap widget that uses google_maps:
import 'dart:html';
import 'package:client_ojp4danube/map/abstract_map_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:google_maps/google_maps.dart';
import 'dart:ui' as ui;
Widget getMap() {
String htmlId = "7";
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(htmlId, (int viewId) {
final myLatlng = new LatLng(30.2669444, -97.7427778);
final mapOptions = new MapOptions()
..zoom = 8
..center = new LatLng(30.2669444, -97.7427778);
final elem = DivElement()
..id = htmlId
..style.width = "100%"
..style.height = "100%"
..style.border = 'none';
final map = GMap(elem, mapOptions);
Marker(MarkerOptions()
..position = myLatlng
..map = map
..title = 'Hello World!');
return elem;
});
return HtmlElementView(viewType: htmlId);
}
class WebMap extends StatefulWidget implements MapWidget {
WebMap({Key? key}) : super(key: key);
@override
State<WebMap> createState() => WebMapState();
}
class WebMapState extends State<WebMap> {
@override
Widget build(BuildContext context) {
return getMap();
}
}
MapWidget getMapWidget() {
print("Intra in get map web ");
return WebMap();
}
- Mobile Map Widget
import 'dart:async';
import 'package:client_ojp4danube/map/abstract_map_widget.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MobileMap extends StatefulWidget implements MapWidget {
MobileMap({Key? key}) : super(key: key);
@override
State<MobileMap> createState() => MobileMapState();
}
class MobileMapState extends State<MobileMap> {
final Completer<GoogleMapController> _controller = Completer();
static const CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
@override
Widget build(BuildContext context) {
return GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
);
}
}
MapWidget getMapWidget() {
return MobileMap();
}
- getMapWidget - stub
import 'package:client_ojp4danube/map/abstract_map_widget.dart';
// Created because importing dart.html on a mobile app breaks the build
MapWidget getMapWidget() => throw UnsupportedError(
'Cannot create a map without dart:html or google_maps_flutter');
- Actually using the abstract widget that will return the widget suited for the platform
import 'package:client_ojp4danube/map/abstract_map_widget.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter ;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: MapWidget()),
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}