Google Maps Place Picker
一个 Flutter 插件,它提供使用谷歌地图 widget 的“地点选择”。
该项目依赖以下包。
使用 Flutter 官方 google_maps_flutter 进行地图绘制
使用 Baseflow 的 geolocator 获取当前位置
使用 hadrienlejard 的 google_maps_webservice 进行地点和地理编码 API
使用 kevmoo 的 tuple 进行构建

支持
如果该软件包对您有帮助或节省了您的时间,请随时给我买杯咖啡! ;)
我获得的咖啡因越多,未来就能做出越有用的项目。
入门
在 https://cloud.google.com/maps-platform/ 获取 API 密钥。
Android
在应用程序清单 android/app/src/main/AndroidManifest.xml 中指定您的 API 密钥
<manifest ...
<application ...
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="YOUR KEY HERE"/>
注意: 从 3.0.0 版本开始,geolocator 插件已切换到 Android Support Libraries 的 AndroidX 版本。这意味着您需要确保您的 Android 项目也已升级以支持 AndroidX。详细说明可在 此处 找到。
精简版是
- 将以下内容添加到您的 "gradle.properties" 文件中
android.useAndroidX=true android.enableJetifier=true
- 确保在 "android/app/build.gradle" 文件中将
compileSdkVersion设置为 28android { compileSdkVersion 28 ... }
- 确保将所有
android.依赖项替换为其 AndroidX 对应项(完整列表可在 https://developer.android.com.cn/jetpack/androidx/migrate 找到)。
iOS
在应用程序代理 ios/Runner/AppDelegate.m 中指定您的 API 密钥
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "GoogleMaps/GoogleMaps.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:@"YOUR KEY HERE"];
[GeneratedPluginRegistrant registerWithRegistry:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
或者在您的 Swift 代码中,在应用程序代理 ios/Runner/AppDelegate.swift 中指定您的 API 密钥
import UIKit
import Flutter
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR KEY HERE")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
通过向应用的 Info.plist 文件添加一个布尔属性来选择加入嵌入式视图预览
键为 io.flutter.embedded_views_preview,值为 YES。
用法
基本用法
您可以使用 Navigator 推送到新页面来使用 PlacePicker。
当用户在地图上选择一个地点时,它将返回结果 (PickResult)。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PlacePicker(
apiKey: APIKeys.apiKey, // Put YOUR OWN KEY here.
onPlacePicked: (result) {
print(result.address);
Navigator.of(context).pop();
},
initialPosition: HomePage.kInitialPosition,
useCurrentLocation: true,
),
),
);
PickResult
| 参数 | 类型 | 描述 |
|---|---|---|
| placeId | 字符串 | 唯一标识一个地点的文本标识符。要检索有关该地点的信息,请将此标识符作为 Places API 请求中的 placeId 字段传递。有关更多信息,请参阅 PlaceId。 |
| geometry | 地理信息 | 包含结果的地理信息,通常包括地点的位置(geocode)和(可选)标识其大致覆盖范围的视口。 |
| address | 字符串 | 一个包含该地点人类可读地址的字符串。此地址通常等同于“邮寄地址”。 |
| types | 列表 <String\> |
包含描述给定结果的要素类型数组。请参阅 支持的类型列表。如果为结果分配了多个类型,XML 响应将包含多个 <type> 元素。 |
| addressComponents | 列表 <AddressComponent\> |
包含适用于此地址的各个组件的数组。 |
在 Google 上获取结果的 更多信息。
PlacePicker
| 参数 | 类型 | 描述 |
|---|---|---|
| apiKey | 字符串 | (必填) 您的 Google Maps API 密钥 |
| onPlacePicked | Callback(PickResult) | 当用户选择地点并选择使用它时调用。如果您手动构建 'selectedPlaceWidgetBuilder',则不会调用此函数,因为您将覆盖默认的“在此处选择”按钮。 |
| initialPosition | LatLng | 创建 Google 地图时地图的初始中心位置。如果将 useCurrentLocation 设置为 true,它将尝试使用 GeoLocator 首先获取设备的当前位置。 |
| useCurrentLocation | 布尔值 | 是否使用设备的当前位置作为初始中心位置 |
| desiredLocationAccuracy | LocationAccuracy | 获取当前位置的精度。默认为“高”。 |
| hintText | 字符串 | 搜索栏的提示文本 |
| searchingText | 字符串 | 搜索进行时出现的文本。默认为“正在搜索…” |
| searchBarHeight | 双精度 | 搜索栏的高度。默认为 40。建议与 contentPadding 一起使用。 |
| contentPadding | EdgeInsetsGeomery | 搜索栏输入文本字段的 InputDecoration 的内容填充 |
| proxyBaseUrl | 字符串 | 用于 Google Maps 上的 API 调用。如果使用代理,可以设置 baseUrl。如果代理设置了 API 密钥,则不需要 apiKey。 |
| httpClient | Client | 用于 Google Maps 上的 API 调用。用于需要身份验证或自定义配置的代理 URL。 |
| autoCompleteDebounceInMilliseconds | 整数 | 自动完成输入的去抖动计时器。默认为 500 |
| cameraMoveDebounceInMilliseconds | 整数 | 使用相机(地图)拖动搜索地点的去抖动计时器。默认为 750 |
| intialMapType | MapType | Google 地图的 MapTypes。默认为 normal。 |
| enableMapTypeButton | 布尔值 | 是否在地图上显示地图类型更改按钮 |
| enableMyLocationButton | 布尔值 | 是否在地图上显示我的位置按钮 |
| onAutoCompleteFailed | Callback(String) | 自动补全搜索失败时调用 |
| onGeocodingSearchFailed | Callback(String) | 通过拖动地图搜索地点失败时调用 |
| onMapCreated | MapCreatedCallback | 创建时返回 Google Maps 控制器 |
| selectedPlaceWidgetBuilder | WidgetBuilder | 在下面部分指定 |
| pinBuilder | WidgetBuilder | 在下面部分指定 |
自定义已选地点可视化
默认情况下,当用户通过自动补全搜索或拖动地图选择地点时,我们会在屏幕底部显示信息(FloatingCard)。
但是,如果您不喜欢这种 UI/UX,只需使用 'selectedPlaceWidgetBuilder' 覆盖它即可。FlocatingCard 小部件可以重复使用,它可以在屏幕周围浮动,或者您可以完全构建一个新小部件,随心所欲。它与地图堆叠在一起,所以您可能想使用 Positioned 小部件。
请注意,使用此自定义将不会调用 [onPlacePicked] 回调,因为它将覆盖浮动卡上的默认“在此处选择”按钮
...
PlacePicker(apiKey: APIKeys.apiKey,
...
selectedPlaceWidgetBuilder: (_, selectedPlace, state, isSearchBarFocused) {
return isSearchBarFocused
? Container()
// Use FloatingCard or just create your own Widget.
: FloatingCard(
bottomPosition: MediaQuery.of(context).size.height * 0.05,
leftPosition: MediaQuery.of(context).size.width * 0.05,
width: MediaQuery.of(context).size.width * 0.9,
borderRadius: BorderRadius.circular(12.0),
child: state == SearchingState.Searching ?
Center(child: CircularProgressIndicator()) :
RaisedButton(onPressed: () { print("do something with [selectedPlace] data"); },),
);
},
...
),
...
| 参数 | 类型 | 描述 |
|---|---|---|
| context | BuildContext | Flutter 的构建上下文值 |
| selectedPlace | PickResult | 用户选定地点的结果数据 |
| state | SearchingState | 搜索操作的状态。(空闲、搜索中) |
| isSearchBarFocused | 布尔值 | 搜索栏当前是否获得焦点,因此键盘已显示 |
自定义图钉
默认情况下,图钉图标在移动时会提供一个非常简单的拾取动画。
但是,您也可以使用“pinBuilder”创建自己的图钉小部件
PlacePicker(apiKey: APIKeys.apiKey,
...
pinBuilder: (context, state) {
if (state == PinState.Idle) {
return Icon(Icons.favorite_border);
} else {
return AnimatedIcon(.....);
}
},
...
),
...
| 参数 | 类型 | 描述 |
|---|---|---|
| context | BuildContext | Flutter 的构建上下文值 |
| state | PinState | 图钉的状态。(正在准备;地图加载时、空闲、拖动中) |
更改默认 FloatingCard(预测图块)的颜色
虽然您可以构建自己的预测列表项,但仍可以使用下面的 ThemeData 来更改默认列表项的样式。
theme: ThemeData.dark().copyWith(
cardColor: Colors.grey, // Background color of the FloatingCard
buttonTheme: ButtonThemeData(
buttonColor: Colors.yellow, // Select here's button color
textTheme: ButtonTextTheme.primary, // Applying this will automatically change text color based on buttonColor. (Button color is dark ? white / is light ? black)
),
textTheme: TextTheme(
body1: TextStyle(color: Colors.white), // This will change the text color of FloatingCard
),
),

