使用谷歌地图在 Flutter 应用中添加地图

Source

我无法想象没有谷歌地图的生活会是什么样子。 我们将它用于所有事情,从寻找到目的地的方向,到搜索附近的餐馆或加油站,再到放大和缩小地图以查看地球上任何位置的街景。

将 Google 地图添加到您的移动应用程序可以为您的用户打开一个全新的世界——从字面上看。 在本教程中,我们将向您展示如何使用官方插件将 Google 地图集成到您的 Flutter 应用程序中。

以下是我们将介绍的内容:

  • 在 Google Cloud Platform 中创建项目

  • 启用地图 API

  • 生成和限制 API 密钥

  • 在 Flutter (Android) 中添加谷歌地图

  • 在 Flutter (iOS) 中添加谷歌地图

  • 添加 GoogleMap小部件

  • Flutter 中的样式化地图

  • 使用 GoogleMap小部件

  • 显示地图列表

  • 拍摄您所在位置的快照

在 Google Cloud Platform 中创建项目

第一步是在 Google Developers Console 创建一个项目。 这是必需的,因为您需要 API 将 Google 地图集成到您的应用程序中。

前往 Google Developers Console 并单击已选择的项目。

单击 新项目 并输入详细信息。

再次单击当前项目名称,您应该会在列表中看到创建的新项目。


超过 20 万开发人员使用 LogRocket 来创造更好的数字体验 了解更多 →


启用地图 API

创建项目后,您必须为 Android 和 iOS 启用 Maps API SDK。

  1. 单击 的库菜单 左侧

  2. 搜索“地图 SDK”

  3. 单击 iOS 版 Maps SDK ,然后单击 启用

  4. 单击 Maps SDK for Android ,然后单击 启用

生成和限制 API 密钥

需要注意的是,对 Google Map API 的访问不是免费的。 因此,您必须为其创建一组 API 密钥并限制其权限,以减少未经授权使用的机会。 这是生成密钥的方法。

  1. 单击 的凭据菜单 左侧

  2. 单击 + 创建凭据 按钮

  3. 选择 API 密钥 选项

如果您同时针对这两个平台,您应该获取两个 API 密钥,以便更好地跟踪它们。

创建 API 密钥后,我强烈建议实施一些限制。 例如,如果您愿意将 API 密钥仅用于地图,那么您应该只允许地图服务使用它。

有两种类型的限制:

  1. 应用程序限制使您能够定义哪种类型的应用程序应有权访问此密钥(即 Android 或 iOS)。 您可以选择适当的选项以确保您创建的密钥仅适用于该特定平台

  2. API 限制使您可以选择使用此密钥可访问哪些服务。 如果它只是用于地图,您将从列表中选择 Maps API

在 Flutter 应用中添加谷歌地图 (Android)

为了能够通过您在上一节中创建的 API 密钥在应用内使用 Google 地图,您必须按照以下说明进行复制和粘贴。

首先,打开你的 Flutter 项目并导航到这个位置的文件: android/app/src/main/AndroidManifest.xml.

接下来,粘贴下面的代码:

<application ...
    <meta-data android:name="com.google.android.geo.API_KEY"
               android:value="YOUR KEY HERE"/>

替换值 "YOUR KEY HERE"使用您创建的 API 密钥。 然后,添加位置权限。


来自 LogRocket 的更多精彩文章:

  • 不要错过 The Replay 来自 LogRocket 的精选时事通讯

  • 了解 LogRocket 的 Galileo 如何消除噪音以主动解决应用程序中的问题

  • 使用 React 的 useEffect 优化应用程序的性能

  • 之间切换 在多个 Node 版本

  • 了解如何 使用 AnimXYZ 为您的 React 应用程序制作动画

  • 探索 Tauri ,一个用于构建二进制文件的新框架

  • 比较 NestJS 与 Express.js


现在 AndroidManifest.xml文件应如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pinkesh.google_maps_flutter">
​
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
​
    <application
        android:label="google_maps_flutter"
        android:icon="@mipmap/ic_launcher">
​
       <!-- TODO: Add your API key here -->
       <meta-data android:name="com.google.android.geo.API_KEY"
           android:value="YOUR KEY HERE"/>
​
        <activity>...</activity>
    </application>
</manifest>

在 Flutter (iOS) 中添加谷歌地图

在 iOS 设备的 Flutter 应用中运行 Google 地图的步骤与 Android 的过程类似。

首先,在应用程序委托中指定您的 API 密钥 ios/Runner/AppDelegate.swift

然后,写 import GoogleMaps顶部的声明以避免 iOS 构建问题。

该文件应如下所示:

import UIKit
import Flutter
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
GMSServices.provideAPIKey("YOUR-KEY")
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

接下来,打开 Xcode 并在 info.plist文件:

<key>NSLocationWhenInUseUsageDescription</key>
<string>The app needs location permission</string>

添加 GoogleMap小部件

完成下面概述的步骤后,您将能够在 Flutter 应用的屏幕上看到 Google 地图。

首先,添加 google_maps_flutter插件到 pubspec.yaml文件。

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: 1.0.0
  google_maps_flutter: ^2.0.1

接下来,将 GoogleMapDart 文件中的小部件。

GoogleMap(
      initialCameraPosition: _kInitialPosition,
    ),

GoogleMap被给予一个 _kInitialPosition,它保存加载时在地图上显示的默认位置。

static final LatLng _kMapCenter =
    LatLng(19.018255973653343, 72.84793849278007);
​
static final CameraPosition _kInitialPosition =
    CameraPosition(target: _kMapCenter, zoom: 11.0, tilt: 0, bearing: 0);

这是显示地图的最低限度代码:

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
​
class SimpleMap extends StatefulWidget {
  @override
  _SimpleMapState createState() =&gt; _SimpleMapState();
}
​
class _SimpleMapState extends State&lt;SimpleMap&gt; {
  static final LatLng _kMapCenter =
      LatLng(19.018255973653343, 72.84793849278007);
​
  static final CameraPosition _kInitialPosition =
      CameraPosition(target: _kMapCenter, zoom: 11.0, tilt: 0, bearing: 0);
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Google Maps Demo'),
      ),
      body: GoogleMap(
        initialCameraPosition: _kInitialPosition,
      ),
    );
  }
}

如果您没有正确查看地图和/或收到如下错误: Cannot enable mylocation layer as location permissions are not granted,您可以尝试执行以下操作之一:

  1. 确保您已请求访问设备位置的适当权限。 清单文件需要添加以下权限:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  2. 如果用户拒绝,请编写逻辑以再次请求权限。 如果他们在权限对话框中选择“不再询问”选项,请编写逻辑通知他们如果没有位置权限,应用程序将无法运行

  3. 检查 Google Cloud 控制台上是否启用了 Map SDK

Flutter 中的样式化地图

如果您正在开发一款特别时尚的产品,并且您希望地图能够反映您的品牌的外观和感觉,则可以自定义地图。

对于本示例,我们将尝试按照以下步骤创建类似于 Uber 的地图样式:

  1. 去 这个网站

  2. 选择银色主题

  3. 单击以调整 地标 和 标签

  4. 恢复公园色彩

  5. 点击 完成

  6. 单击 复制 JSON 按钮

现在有了地图样式,您就可以将其放入应用程序并让插件使用它。

首先,创建一个 assets应用程序根目录下的文件夹。

接下来,创建一个 map_style.json文件里面,并粘贴您复制的代码片段。

在中添加引用 pubspec.yaml文件:

assets:
 - map_style.json

通过在地图中加载新样式 GoogleMapController. 更新后的代码应如下所示:

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
​
class SimpleMap extends StatefulWidget {
  @override
  _SimpleMapState createState() =&gt; _SimpleMapState();
}
​
class _SimpleMapState extends State&lt;SimpleMap&gt; {
  static final LatLng _kMapCenter =
      LatLng(19.018255973653343, 72.84793849278007);
​
  static final CameraPosition _kInitialPosition =
      CameraPosition(target: _kMapCenter, zoom: 11.0, tilt: 0, bearing: 0);
​
  GoogleMapController _controller;
​
  Future&lt;void&gt; onMapCreated(GoogleMapController controller) async {
    _controller = controller;
    String value = await DefaultAssetBundle.of(context)
        .loadString('assets/map_style.json');
    _controller.setMapStyle(value);
  }
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Google Maps Demo'),
      ),
      body: GoogleMap(
        initialCameraPosition: _kInitialPosition,
        onMapCreated: onMapCreated,
      ),
    );
  }
}
onMapCreated is a callback that’s called when the map is ready to use. It provides the GoogleMapController, which is really helpful for performing certain actions on the map. For this example, we used it to set the map style via the _controller.setMapStyle(value); method.

这是输出:

修改地图 GoogleMap小部件

这 GoogleMap小部件为您提供了很大的灵活性来修改地图。 让我们探索一些方法来做到这一点。

更改地图类型

有多种类型的可用地图,包括卫星地图、地形地图和混合地图。 您可以简单地将所需的类型设置为 mapType小部件的属性:

GoogleMap(
  initialCameraPosition: _kInitialPosition,
  onMapCreated: onMapCreated,
  mapType: MapType.satellite,
);

启用我的位置按钮

默认情况下,地图将显示 initialCameraPosition小部件的参数(或您以编程方式提供给地图的任何其他位置)。 如果用户想返回他们的位置,设置 myLocationEnabled至 true将完成这项工作。

设备静止时屏幕上会出现一个小蓝点,如果设备移动,屏幕上会出现人字形。

GoogleMap(
  initialCameraPosition: _kInitialPosition,
  onMapCreated: onMapCreated,
  myLocationEnabled: true,
);

人们经常想知道“如何在 Flutter 中更改我在 Google 地图上的位置?” 这个问题的答案是你不能在 Flutter 中更改你在谷歌地图上的位置。 您的位置由您在地球上的地理位置通过 GPS 计算确定,除非您的设备移动到新位置,否则无法修改。

如果您想更改“我的位置”按钮的位置,您可以创建一个 FloatingActionButton (FAB) 来替换库存的“我的位置”按钮并将其放置在屏幕上您想要的任何位置。 您只需要编写逻辑,以便在单击按钮时将地图的摄像头置于您的位置。 以下是逻辑可能的样子:

void _currentLocation() async {
​
    // Create a map controller
    final GoogleMapController controller = await _controller.future;
    LocationData currentLocation;
    var location = new Location();
    try {
        // Find and store your location in a variable
        currentLocation = await location.getLocation();
    } on Exception {
        currentLocation = null;
    }
​
    // Move the map camera to the found location using the controller
    controller.animateCamera(CameraUpdate.newCameraPosition(
        CameraPosition(
            bearing: 0,
            target: LatLng(currentLocation.latitude, currentLocation.longitude),
            zoom: 17.0,
        ),
    ));
}

在地图上创建标记

标记是显示特定位置的好方法。

要查看如何在地图上创建标记,请参阅以下代码:

Set<Marker> _createMarker() {
  return {
    Marker(
        markerId: MarkerId("marker_1"),
        position: _kMapCenter,
        infoWindow: InfoWindow(title: 'Marker 1'),
        rotation: 90),
    Marker(
      markerId: MarkerId("marker_2"),
      position: LatLng(18.997962200185533, 72.8379758747611),
    ),
  };
}

集合中的每个标记都需要一些参数,这些参数对于传达信息很有用。 第一个标记被赋予 infowindow,它显示了它的 ID(你可以在这里写任何东西来描述这个地方)和一个 rotation90度。 这 rotation当您在同一个地方有多个标记时,param 非常有用 - 例如,单个塔上的多个单元天线。

GoogleMap(
  initialCameraPosition: _kInitialPosition,
  onMapCreated: onMapCreated,
  markers: _createMarker(),
);

启用交通模式

您可以通过简单地设置值来打开交通模式 trafficEnabled至 true.

GoogleMap(
  initialCameraPosition: _kInitialPosition,
  onMapCreated: onMapCreated,
  trafficEnabled: true,
);

显示地图列表

假设您想通过显示标记来显示地图列表,以帮助用户定位卫星办公室、其他医院等。

首先,创建一个 GridView显示 Google 地图小部件列表。 您可以设置 initialCameraPosition. 放 liteModeEnabled至 true. 这会创建您无法与之交互的地图图像:

GridView.count(
  crossAxisCount: 2,
  crossAxisSpacing: 8,
  mainAxisSpacing: 8,
  // Generate 100 widgets that display their index in the List.
  children: List.generate(10, (index) {
    return Center(
      child: GoogleMap(
        initialCameraPosition: _kInitialPosition,
        markers: _createMarker(),
        liteModeEnabled: true,
      ),
    );
  }),
)

创建一组标记并确保为它分配了不同的位置。

Set<Marker> _createMarker() {
  return {
    Marker(
        markerId: MarkerId("marker_1"),
        position: _kMapCenter),
    Marker(
      markerId: MarkerId("marker_2"),
      position: LatLng(18.997962200185533, 72.8379758747611),
    ),
  };
}

在撰写本文时,此功能仅适用于 Android。

拍摄您所在位置的快照

拍摄您的位置快照并与他人快速分享您的旅程的能力是一项非常酷的功能。

首先,在您的应用程序的某处创建一个按钮。 这 _controller.takeSnapshot()方法将通过单击按钮为您完成其余的魔术。

FloatingActionButton(
  onPressed: () async {
    final imageBytes = await _controller.takeSnapshot();
    setState(() {
      _imageBytes = imageBytes;
    });
  },
  child: Icon(Icons.fullscreen),
)

接下来,创建一个小部件来显示快照:

Container(
  decoration: BoxDecoration(color: Colors.blueGrey[50]),
  height: 150,
  width: 120,
  child: _imageBytes != null ? Image.memory(_imageBytes) : null,
)

而已! 完整的代码可以在 GitHub 上找到。

结论

在本教程中,我们展示了如何在 Flutter 应用中集成 Google 地图,并探索了一些自定义地图外观的方法。 我们介绍了如何在 Flutter 应用程序中启用 Maps API、生成和限制 API 密钥以及设置、样式和修改地图。

将 Google 地图功能添加到您的应用程序打开了一个充满可能性的世界。 掌握了基础知识后,您就可以开始在 Flutter 应用程序中构建基于位置的功能和交互式地图了。

LogRocket :全面了解您的网络和移动应用程序

LogRocket 是一个前端应用程序监控解决方案,可让您重现问题,就好像它们发生在您自己的浏览器中一样。 无需猜测错误发生的原因,或要求用户提供屏幕截图和日志转储,LogRocket 可让您重播会话以快速了解问题所在。 无论框架如何,它都可以完美地与任何应用程序配合使用,并且具有用于记录来自 Redux、Vuex 和 @ngrx/store 的附加上下文的插件。

除了记录 Redux 操作和状态之外,LogRocket 还记录控制台日志、JavaScript 错误、堆栈跟踪、带有标头 + 正文的网络请求/响应、浏览器元数据和自定义日志。 它还检测 DOM 以记录页面上的 HTML 和 CSS,即使是最复杂的单页和移动应用程序也能重新创建像素完美的视频。

LogRocket :全面了解您的网络和移动应用程序

ImagesTool(imagestool.com),在线免费图片视频处理网站,没有数量限制!

LogRocket 是一个前端应用程序监控解决方案,可让您重现问题,就好像它们发生在您自己的浏览器中一样。 无需猜测错误发生的原因,或要求用户提供屏幕截图和日志转储,LogRocket 可让您重播会话以快速了解问题所在。 无论框架如何,它都可以完美地与任何应用程序配合使用,并且具有用于记录来自 Redux、Vuex 和 @ngrx/store 的附加上下文的插件。

除了记录 Redux 操作和状态之外,LogRocket 还记录控制台日志、JavaScript 错误、堆栈跟踪、带有标头 + 正文的网络请求/响应、浏览器元数据和自定义日志。 它还检测 DOM 以记录页面上的 HTML 和 CSS,即使是最复杂的单页和移动应用程序也能重新创建像素完美的视频。