当前位置: 首页 > 知识库问答 >
问题:

在flutter中为手机和网络使用谷歌地图

骆照
2023-03-14

我正在开发一个颤动应用程序,它应该有一个通用的Web和移动设备代码库。

我的应用程序将有一个谷歌地图,据我所知,没有一个软件包可以满足所有平台。

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实际上不是一个可用的版本,据我所知,(如果我错了请纠正我),它实际上使用了另一个不是由flutter团队开发的包google_maps6.0.0

google_maps_flutter_web的目标可能是拥有与google_maps_fluttergoogle_maps_flutter_platform_interface)相同的api并无缝使用它,但我真的找不到如何使用它的示例...

我应该怎么做?我对google_maps_flutter_web的任何改变都是错误的,它实际上是有效的?或者我应该尝试使用实际上适用于Web的google_maps,然后根据kIsWeb切换小部件?

共有2个答案

程皓轩
2023-03-14

编辑:一个新的官方插件已经发布:https://pub.dev/packages/google_maps_flutter_web。它已经可以与现有的google_maps_flutter插件一起使用,只需在 web/index.html 中添加您的api脚本即可。

正如用户exilonX建议的那样,目前(2012年4月)在Flutter web和移动设备上使用谷歌地图的方式是基于设备动态加载库。然而,他的回答缺少一些重要的细节。我花了将近一个小时来完成他的工作,因此我在这里分享了一个更清晰、更有条理的解决方案,希望能节省你一些时间(由于编辑队列太长,我无法编辑他的答案)。

文件夹结构:

\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 MapWidget:

该文件将包含web上显示的谷歌地图:

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(),
        ),
      ),
    );

注意:为了使地图工作,您需要使用键进行设置。请参阅移动和网络的官方图书馆文档。

谭奕
2023-03-14

最终,我使用< code>google_maps和这个答案作为灵感找到了一个变通方法:

  1. 抽象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();
    }
    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://medium.com/flutter-io/google-maps-and-flutter-cfb330f9a245“在颤振中添加谷歌地图。我用谷歌地图键更新了android清单,并添加了访问fine_位置的权限。我的模拟器上出现了白色屏幕,没有地图。我花了很多时间试图修复它,但徒劳。我还尝试了插件的示例用法。”https://pub.dartlang.org

  • 02-14 13:09:38.184:e/databaseUtils(2348):向包写入异常02-14 13:09:38.184:e/databaseUtils(2348):java.lang.securityexception:权限拒绝:用户的get/set设置要求以用户-2的身份运行,但从用户0调用;这需要Android.permission.interact_across_users_fu

  • 我用谷歌地球创建了一个kml文件,它使用外部图像创建了一个覆盖层。它工作得很好,我想找到一种相当方便的转换kml的方法,这样谷歌地图就可以以类似的方式读取和显示它。 谷歌地图不能处理谷歌地球坐标,所以我试图自己转换它们。例如,我替换了地球坐标: 使用等效地图坐标: 不幸的是,两者并不完全“对等”。“地图覆盖”稍微关闭,旋转不正确。 以下是两张照片: 地球实例 地图示例 我明白为什么它不起作用,但我

  • 我与使用google-webaffts有一个非常严重的冲突。好的,这是代码: 这是在头: 这是在css文件中: “奥斯瓦尔德”是由3种字体组成的字体系列: 书(300) 正常(400) 粗体(700) 正如你看到的那样..我只加载了粗体字(700)。(你可以在查询中看到)它一直工作到这里,但是… 问题是: 我的计算机上安装了3种字体(300,400,700)的桌面版本,只要这些字体被激活…浏览器在

  • 我正在尝试按照本教程在flutter中设置谷歌地图,但我遇到了一些问题。我的应用程序运行,但我看到一个白色屏幕,没有发生任何事情,并且将以下错误打印到终端: 这很奇怪,因为我的看起来像这样: 这正是错误所要求的,所以我不知道出了什么问题。我查看了其他线程,并做了一些建议,比如运行删除应用程序、并重试,这也不起作用。 这些是我在 我还想添加,但是我得到了以下错误 我也尝试了一些其他版本,但我一直出错

  • 我在我的flutter应用程序中使用google_maps_flutter来使用谷歌地图我有自定义标记图标,我用BitmapDescriptor.from字节(mark erIcon)加载它,但我想用一些文本显示Url的图标。 这就是我们要达到的目的 是否可以通过flutter或任何可以动态创建图像的外部图像依赖来实现相同的效果。