Flutter地点选择器插件google_places_picker_advance的使用
Flutter地点选择器插件google_places_picker_advance的使用
Google Maps Place Picker
google_places_picker_advance
是一个基于 Flutter 的插件,通过 Google Maps
提供地点选择功能。
该项目依赖以下包:
- 使用 Flutter 官方的
google_maps_flutter
进行地图展示。 - 使用 Baseflow 的
geolocator
获取当前位置。 - 使用 hadrienlejard 的
google_maps_webservice
调用 Place 和 Geocoding API。 - 使用 kevmoo 的
tuple
构建器。
支持
如果你觉得这个插件对你有用或节省了时间,请不要犹豫买杯咖啡支持我!😉
更多的咖啡因意味着未来可以开发更多有用的功能。
开始使用
获取 API 密钥
- 在 Google Cloud Console 获取 API 密钥。
- 启用以下 API:
- Maps SDK for Android
- Maps SDK for iOS
- Maps JavaScript API
- Places API
- Geolocation API
- Geocoding API
你也可以在这里找到详细的启用步骤:Google Maps 平台入门指南。
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
插件切换到了 AndroidX 版本的支持库。因此你需要确保你的 Android 项目也升级到支持 AndroidX。详细说明可以查看 Flutter 官方文档。
快速解决方案:
- 在
gradle.properties
文件中添加以下内容:android.useAndroidX=true android.enableJetifier=true
- 在
android/app/build.gradle
文件中设置compileSdkVersion
为 32:android { compileSdkVersion 32 ... }
- 将所有
android.
依赖替换为其 AndroidX 对应版本(完整列表可参考 AndroidX 迁移指南)。
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
文件中添加以下内容以访问设备位置:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to location when open and in the background.</string>
此外,还需要在 XCode 项目中启用 Background Modes
功能,并选择 Location Updates
。
最后,在 Info.plist
文件中添加以下键值对以启用嵌入式视图预览:
<key>io.flutter.embedded_views_preview</key>
<true/>
使用方法
基本使用
可以通过 Navigator
推动到新页面,或者直接作为任何小部件的子组件使用。
当用户在地图上选择一个地点时,它会通过 onPlacePicked
回调返回结果。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PlacePicker(
apiKey: APIKeys.apiKey, // 替换为你的 API 密钥
onPlacePicked: (result) {
print(result.address);
Navigator.of(context).pop();
},
initialPosition: LatLng(37.7749, -122.4194), // 初始位置(旧金山)
useCurrentLocation: true, // 使用当前设备位置
),
),
);
PickResult 参数说明
以下是 PickResult
的参数及其描述:
参数名称 | 类型 | 描述 |
---|---|---|
placeId | String | 唯一标识地点的文本标识符。详见 PlaceId 文档。 |
geometry | Geometry | 包含地点的几何信息,通常包括地理位置和视口。 |
formattedAddress | String | 地点的人类可读地址,通常等同于邮政地址。 |
types | List<String> | 描述该地点特征的数组。详见 支持的类型列表。 |
addressComponents | List<AddressComponent> | 地址的相关组件数组。 |
注:以下结果仅在使用自动完成搜索或设置 usePlaceDetailSearch
为 true
时可用。
PickResult 可选参数
参数名称 | 类型 | 描述 |
---|---|---|
adrAddress | String | 地址的 adr microformat 表示形式。 |
formattedPhoneNumber | String | 地点的电话号码,以本地格式显示。 |
id | String | (未在 Google 文档中记录) |
reference | String | (未在 Google 文档中记录) |
icon | String | 地图上显示此结果建议的图标 URL。 |
name | String | 返回结果的人类可读名称。 |
openingHours | OpeningHoursDetail | 营业时间信息。 |
photos | List<Photo> | 包含图像引用的照片数组。 |
internationalPhoneNumber | String | 地点的国际格式电话号码。 |
priceLevel | PriceLevel | 地点的价格等级,范围为 0 到 4。 |
rating | num | 地点的评分,基于用户评论,范围为 1.0 到 5.0。 |
scope | String | (未记录) |
url | String | 地点的官方 Google 页面 URL。 |
vicinity | String | 简化地址,包括街道名称、门牌号和所在地区,但不包括省份、邮政编码或国家。 |
utcOffset | num | 此地点当前时区与 UTC 的偏移量(分钟)。 |
website | String | 地点的权威网站。 |
reviews | List<Review> | 最多包含五个评论的 JSON 数组。 |
更多关于结果的信息可以参考 Google Places API 文档。
PlacePicker 参数说明
参数名称 | 类型 | 描述 |
---|---|---|
apiKey | String | 必填项,Google Maps API 密钥。 |
onPlacePicked | Callback(PickResult) | 用户选择地点并确认后触发回调。 |
initialPosition | LatLng | 初始地图中心位置。如果 useCurrentLocation 设置为 true ,将尝试获取设备的当前位置。 |
useCurrentLocation | bool | 是否使用设备的当前位置作为初始中心位置。 |
desiredLocationAccuracy | LocationAccuracy | 获取当前位置的精度,默认为高精度。 |
hintText | String | 搜索栏的提示文字。 |
searchingText | String | 搜索时显示的文字,默认为“正在搜索…”。 |
proxyBaseUrl | String | 用于 Google Maps API 调用的代理基础 URL。 |
httpClient | Client | 用于 Google Maps API 调用的 HTTP 客户端。 |
autoCompleteDebounceInMilliseconds | int | 自动完成输入的防抖计时器,默认为 500 毫秒。 |
cameraMoveDebounceInMilliseconds | int | 地图拖动时搜索的防抖计时器,默认为 750 毫秒。 |
intialMapType | MapType | Google Maps 的地图类型,默认为普通模式。 |
enableMapTypeButton | bool | 是否显示地图类型切换按钮。 |
enableMyLocationButton | bool | 是否显示我的位置按钮。 |
usePinPointingSearch | bool | 默认为 true ,允许用户拖动地图并获取指针指向的位置信息。 |
usePlaceDetailSearch | bool | 默认为 false ,设置为 true 时,拖动地图搜索将获取更详细的结果,但会增加一次 Place Detail API 请求。 |
onAutoCompleteFailed | Callback(String) | 自动完成搜索失败时触发的回调。 |
onGeocodingSearchFailed | Callback(String) | 拖动地图搜索失败时触发的回调。 |
onMapCreated | MapCreatedCallback | 地图创建完成后返回控制器。 |
selectedPlaceWidgetBuilder | WidgetBuilder | 下面部分有详细介绍。 |
pinBuilder | WidgetBuilder | 下面部分有详细介绍。 |
autocompleteOffset | num | 服务匹配预测的最后一个字符的位置。 |
autocompleteRadius | num | 返回地点结果的距离范围(单位:米)。 |
autocompleteLanguage | String | 结果的语言代码,详见 Google Maps 语言支持。 |
autocompleteComponents | List<Components> | 限制搜索结果的地点分组。最多可以按 5 个国家进行过滤。 |
autocompleteTypes | List<String> | 返回地点结果的类型。详见 Place Types 文档。 |
strictbounds | bool | 返回仅限于指定区域内的地点。 |
region | String | 地区代码,指定为 ccTLD(国家顶级域名)的两位字符值。 |
selectInitialPosition | bool | 是否在初始地图加载时显示选定地点。默认为 false 。 |
resizeToAvoidBottomInset | bool | 引用 Scaffold 的 resizeToAvoidBottomInset 属性。 |
initialSearchString | String | 自动完成搜索的初始搜索字符串。 |
searchForInitialValue | bool | 是否在启动时自动搜索初始值。 |
forceAndroidLocationManager | bool | 在 Android 设备上可以设置为 true ,强制使用 LocationManager 来确定位置,而不是 FusedLocationProviderClient 。 |
myLocationButtonCooldown | int | myLocationButton 的冷却时间,单位为秒,默认为 10 秒。 |
forceSearchOnZoomChanged | bool | 是否允许在缩放更改时进行地点搜索。默认为 false 。 |
automaticallyImplyAppBarLeading | bool | 默认情况下顶部有一个返回按钮。设置为 false 将移除返回按钮。 |
autocompleteOnTrailingWhitespace | bool | 是否允许在搜索末尾空格时运行自动完成。默认为 false 。 |
更多关于自动完成搜索的信息可以参考 Google Places 自动完成文档。
自定义选择地点的可视化效果
默认情况下,当用户通过自动完成搜索或拖动地图选择地点时,信息会显示在屏幕底部(FloatingCard)。
如果你不喜欢这种 UI/UX,可以通过 selectedPlaceWidgetBuilder
覆盖默认实现。可以复用 FloatingCard
或者根据需求构建全新的小部件。它堆叠在地图之上,因此可能需要使用 Positioned
小部件。
注意:使用此自定义选项不会触发 [onPlacePicked]
回调,因为它会覆盖默认的“选择这里”按钮。
PlacePicker(
apiKey: APIKeys.apiKey,
onPlacePicked: (result) {
print(result.address);
Navigator.of(context).pop();
},
initialPosition: HomePage.kInitialPosition,
useCurrentLocation: true,
selectedPlaceWidgetBuilder: (
BuildContext context,
PickResult selectedPlace,
SearchingState state,
bool isSearchBarFocused,
) {
return isSearchBarFocused
? Container()
// 可以复用 FloatingCard 或自定义小部件。
: FloatingCard(
bottomPosition: 0.0, // 使用 MediaQuery.of(context) 会导致重建。详见文档。
leftPosition: 0.0,
rightPosition: 0.0,
width: 500,
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 | bool | 搜索栏是否当前聚焦,键盘是否显示。 |
自定义地标
默认情况下,地标图标具有简单的拖动动画。
你可以通过 pinBuilder
创建自己的地标小部件。
PlacePicker(
apiKey: APIKeys.apiKey,
pinBuilder: (BuildContext context, PinState state) {
if (state == PinState.Idle) {
return Icon(Icons.favorite_border);
} else {
return AnimatedIcon(...);
}
},
),
参数说明:
参数名称 | 类型 | 描述 |
---|---|---|
context | BuildContext | Flutter 的构建上下文值。 |
state | PinState | 地标状态。(准备中、加载中、拖动中) |
更改默认 FloatingCard 的颜色
虽然你可以构建自己的预测小部件,但仍然可以通过 themeData
更改默认小部件的样式:
// 浅色主题
final ThemeData lightTheme = ThemeData.light().copyWith(
// FloatingCard 的背景颜色
cardColor: Colors.white,
buttonTheme: ButtonThemeData(
// “选择这里”按钮的颜色
buttonColor: Colors.black,
textTheme: ButtonTextTheme.primary,
),
);
// 深色主题
final ThemeData darkTheme = ThemeData.dark().copyWith(
// FloatingCard 的背景颜色
cardColor: Colors.grey,
buttonTheme: ButtonThemeData(
// “选择这里”按钮的颜色
buttonColor: Colors.yellow,
textTheme: ButtonTextTheme.primary,
),
);
更多关于Flutter地点选择器插件google_places_picker_advance的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter地点选择器插件google_places_picker_advance的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
google_places_picker_advance
是一个用于 Flutter 的插件,它提供了一个高级的地点选择器,允许用户通过 Google Places API 选择地点。这个插件可以帮助你轻松地集成 Google Places 功能到你的 Flutter 应用中,让用户能够搜索并选择地点。
以下是如何使用 google_places_picker_advance
插件的步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 google_places_picker_advance
插件的依赖:
dependencies:
flutter:
sdk: flutter
google_places_picker_advance: ^1.0.0 # 请检查最新版本
然后运行 flutter pub get
来安装依赖。
2. 获取 Google Places API 密钥
在使用这个插件之前,你需要在 Google Cloud Platform 上启用 Google Places API,并获取一个 API 密钥。
- 访问 Google Cloud Console.
- 创建一个新项目或选择一个现有项目。
- 导航到 “API 和服务” > “启用 API 和服务”。
- 搜索并启用 “Places API”。
- 在 “API 和服务” > “凭据” 中创建一个 API 密钥。
3. 配置 API 密钥
在你的 Flutter 项目中,你需要在 Android 和 iOS 平台上配置 API 密钥。
Android
在 android/app/src/main/AndroidManifest.xml
文件中添加以下内容:
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY"/>
iOS
在 ios/Runner/AppDelegate.swift
文件中添加以下内容:
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR_API_KEY")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
4. 使用插件
在你的 Flutter 代码中,你可以使用 GooglePlacesPickerAdvance
来启动地点选择器。
import 'package:flutter/material.dart';
import 'package:google_places_picker_advance/google_places_picker_advance.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Google Places Picker'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
// 启动地点选择器
PlacePickerResult result = await GooglePlacesPickerAdvance.showPlacePicker(
apiKey: 'YOUR_API_KEY',
);
if (result != null) {
print('Selected Place: ${result.name}');
print('Address: ${result.formattedAddress}');
print('Latitude: ${result.geometry.location.lat}');
print('Longitude: ${result.geometry.location.lng}');
} else {
print('No place selected');
}
},
child: Text('Pick a Place'),
),
),
);
}
}