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 构建器。

支持

如果你觉得这个插件对你有用或节省了时间,请不要犹豫买杯咖啡支持我!😉
更多的咖啡因意味着未来可以开发更多有用的功能。

Buy Me A Coffee


开始使用

获取 API 密钥

  1. Google Cloud Console 获取 API 密钥。
  2. 启用以下 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 官方文档

快速解决方案:

  1. gradle.properties 文件中添加以下内容:
    android.useAndroidX=true
    android.enableJetifier=true
    
  2. android/app/build.gradle 文件中设置 compileSdkVersion 为 32:
    android {
      compileSdkVersion 32
      ...
    }
    
  3. 将所有 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> 地址的相关组件数组。

:以下结果仅在使用自动完成搜索或设置 usePlaceDetailSearchtrue 时可用。

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

1 回复

更多关于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 密钥。

  1. 访问 Google Cloud Console.
  2. 创建一个新项目或选择一个现有项目。
  3. 导航到 “API 和服务” > “启用 API 和服务”。
  4. 搜索并启用 “Places API”。
  5. 在 “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'),
        ),
      ),
    );
  }
}
回到顶部