exi*_*onX 7 google-maps flutter flutter-web google-maps-flutter
我正在开发一个 flutter 应用程序,该应用程序应该有一个适用于网络和移动设备的通用代码库。
我的应用程序将有一个谷歌地图,据我所知,没有一个包可以满足所有平台。
google_maps_flutter - seems to work only for mobile (IOS / Android)
google_maps_flutter_web - seems to work only for web
Run Code Online (Sandbox Code Playgroud)
因此,很可能我必须使用这些单独的包创建两个单独的 MapWidget,一个用于网络,一个用于移动设备。
对于移动设备:
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);
},
);
}
}
Run Code Online (Sandbox Code Playgroud)
对于网络来说,它有点复杂,google_maps_flutter_web从我的理解来看,它似乎实际上不是一个可用的版本(如果我错了,请纠正我),并且它实际上使用了另一个不是由 flutter 团队开发的包google_maps 6.0.0。
可能的目标google_maps_flutter_web是拥有与google_maps_flutter( google_maps_flutter_platform_interface) 相同的 api 并无缝使用它,但我真的找不到如何使用它的示例......
我该怎么办?我对 google_maps_flutter_web 有什么误解并且它确实有效吗?或者我应该尝试使用google_maps实际上适用于网络的工具,然后根据 切换小部件kIsWeb?
编辑:一个新的官方插件已发布:https ://pub.dev/packages/google_maps_flutter_web 。它已经可以与现有的 google_maps_flutter 插件配合使用,只需在 web/index.html 中添加您的 api 脚本即可。
正如用户 exilonX 所建议的,在 Flutter Web 和移动设备上使用 Google 地图的当前方法(22 年 4 月)是根据设备动态加载库。然而,他的回答缺乏一些重要的细节。我花了将近 1 个小时才让他的工作正常工作,因此我在这里分享一个更清晰、更有组织的解决方案,希望它能为您节省一些时间(由于编辑队列很长,我无法编辑他的答案)。
文件夹结构:
\widget
\map_widget.dart
\web_map_widget.dart
\mob_map_widget.dart
\map_widget_stub.dart
Run Code Online (Sandbox Code Playgroud)
地图小部件:
在该文件中,map_widget.dart您将拥有抽象的 MapWidget:
import 'package:flutter/material.dart';
import 'map_widget_stub.dart'
if (dart.library.html) 'web_map_widget.dart'
if (dart.library.io) 'mob_map_widget.dart';
abstract class MapWidget extends StatefulWidget {
factory MapWidget() => getMapWidget();
}
Run Code Online (Sandbox Code Playgroud)
注意:条件导入中唯一需要的半列位于第二个 if 的末尾。
网络地图小部件:
该文件将包含网络上显示的谷歌地图:
import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:google_maps/google_maps.dart';
import 'map_widget.dart';
MapWidget getMapWidget() => WebMap();
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) {
final String htmlId = "map";
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(htmlId, (int viewId) {
final mapOptions = MapOptions()
..zoom = 15.0
..center = LatLng(35.7560423, 139.7803552);
final elem = DivElement()..id = htmlId;
final map = GMap(elem, mapOptions);
map.onCenterChanged.listen((event) {});
map.onDragstart.listen((event) {});
map.onDragend.listen((event) {});
Marker(MarkerOptions()
..position = map.center
..map = map);
return elem;
});
return HtmlElementView(viewType: htmlId);
}
}
Run Code Online (Sandbox Code Playgroud)
在这里您可以找到有关网络实施的更多详细信息。
移动地图小工具:
该文件包含移动设备(android/ios)的实现:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'map_widget.dart';
MapWidget getMapWidget() => MobileMap();
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 _kFalentexHouse =
CameraPosition(target: LatLng(44.497858579692135, 11.336362079086408));
@override
Widget build(BuildContext context) {
return GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: _kFalentexHouse,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
);
}
}
Run Code Online (Sandbox Code Playgroud)
存根
最后,您需要一个存根:
import 'map_widget.dart';
//the error is shown in case of wrong version loaded on wrong platform
MapWidget getMapWidget() => throw UnsupportedError(
'Cannot create a map without dart:html or google_maps_flutter');
Run Code Online (Sandbox Code Playgroud)
用法
现在您可以将 MapWidget 小部件用作普通小部件:
Scaffold(
body: Center(
child: SizedBox(
height: 300,
width: 300,
child: MapWidget(),
),
),
);
Run Code Online (Sandbox Code Playgroud)
注意:为了使地图正常工作,您需要使用密钥进行设置。请参阅移动和网络的官方库文档。
最终我找到了一个解决方法,使用google_maps这个答案作为灵感:
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();
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
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');
Run Code Online (Sandbox Code Playgroud)
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.
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4579 次 |
| 最近记录: |