![](/img/trans.png)
[英]Is using flutter for both mobile and web for a social media platform feasible?
[英]Using Google Maps in flutter for both mobile and web
我正在開發一個 flutter 應用程序,該應用程序應該具有 web 和移動設備的通用代碼庫。
我的應用程序將有一個谷歌 map,據我所知,沒有一個 package 可以滿足所有平台。
google_maps_flutter - seems to work only for mobile (IOS / Android)
google_maps_flutter_web - seems to work only for web
所以很可能我必須創建兩個單獨的 MapWidgets,一個用於 web,另一個用於使用這些單獨包的移動設備。
對於手機:
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);
},
);
}
}
對於 web,它有點復雜,據我了解, google_maps_flutter_web
似乎實際上不是一個可用版本(如果我錯了請糾正我)並且它實際上使用另一個 package 不是由 flutter 團隊google_maps 6.0.0
開發的google_maps 6.0.0
。
google_maps_flutter_web
的目標可能是擁有與google_maps_flutter
( google_maps_flutter_platform_interface
) 相同的 api 並無縫使用它,但我真的找不到如何使用它的示例......
我應該怎么go一下這個? 我對 google_maps_flutter_web 有什么誤解,它真的有效嗎? 或者我應該嘗試使用實際適用於google_maps
的 google_maps 並僅根據kIsWeb
切換小部件?
最終我找到了一個使用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();
}
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();
}
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();
}
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');
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.
);
}
}
編輯:發布了一個新的官方插件: https://pub.dev/packages/google_maps_flutter_web 。 它已經可以與現有的 google_maps_flutter 插件一起使用,只需在 web/index.html 中添加您的 api 腳本。
正如用戶 exilonX 所建議的那樣,目前(22 年 4 月)在 Flutter web 和移動設備上使用 Google 地圖的方式是根據設備動態加載庫。 但是,他的回答缺少一些重要的細節。 我花了將近 1 小時才讓他的工作正常進行,因此我在這里分享一個更清晰、更有條理的解決方案,希望它能為您節省一些時間(由於編輯隊列很長,我無法編輯他的答案)。
文件夾結構:
\widget
\map_widget.dart
\web_map_widget.dart
\mob_map_widget.dart
\map_widget_stub.dart
地圖小部件:
在文件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();
}
注意:條件導入所需的唯一半列是在第二個 if 的末尾。
Web 地圖小部件:
此文件將包含 web 上顯示的 google map:
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);
}
}
在這里您可以找到有關 web 實現的更多詳細信息。
移動地圖小部件:
此文件包含移動設備(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);
},
);
}
}
存根
最后,你需要一個存根:
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');
用法
現在您可以將小部件 MapWidget 用作普通小部件:
Scaffold(
body: Center(
child: SizedBox(
height: 300,
width: 300,
child: MapWidget(),
),
),
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.