You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Flutter实现基于Google Places API的地址输入下拉建议

实现Flutter端Google Places地址输入建议功能

嘿,刚好我之前做过类似的Flutter地址输入功能,其实实现起来真的没那么麻烦!虽然Flutter官方确实没有开箱即用的组件,但结合Google Places API,咱们一步步来就能搞定~

1. 前期准备

  • 先去Google Cloud控制台启用Places API,生成专属的API密钥,记得给密钥配置应用限制(比如绑定Android的包名、SHA-1指纹,iOS的Bundle ID),避免被恶意调用。
  • 如果选择手动调用API,需要添加http包到pubspec.yaml;如果用第三方包简化开发,可以选社区成熟的flutter_google_places。

2. 两种实现方案

方案一:手动调用API(自定义程度更高)

这种方式适合需要完全自定义UI的场景,步骤如下:

  • 用TextField作为输入载体,监听onChanged事件。这里一定要加防抖处理(比如用Timer延迟300ms再发送请求),避免用户每敲一个字符就发起一次API调用,既浪费资源又容易触发限流。
  • 构造Google Places Autocomplete的请求URL,示例如下:
    https://maps.googleapis.com/maps/api/place/autocomplete/json?input=用户输入内容&key=你的API密钥&components=country:cn
    
    其中components参数可以用来限制搜索国家(比如country:cn只搜中国境内地点),可选但推荐加上。
  • 用http包发送GET请求,解析返回的JSON数据,提取出地点名称、Place ID等核心信息。
  • 在输入框下方展示建议列表(可以用Stack+ListView或者Overlay实现悬浮列表),当用户点击某一项时,把选中的地点名称填充到输入框,还可以进一步调用Place Details API获取经纬度等详细信息。

方案二:用第三方包快速实现

如果不需要太复杂的自定义,社区的flutter_google_places包能帮咱们省不少事,示例代码如下:

import 'package:flutter_google_places/flutter_google_places.dart';
import 'package:google_maps_webservice/places.dart';
import 'package:flutter/material.dart';

class AddressInputPage extends StatefulWidget {
  const AddressInputPage({super.key});

  @override
  State<AddressInputPage> createState() => _AddressInputPageState();
}

class _AddressInputPageState extends State<AddressInputPage> {
  final TextEditingController _addressController = TextEditingController();
  final String _apiKey = "你的API密钥";
  final GoogleMapsPlaces _places = GoogleMapsPlaces(apiKey: "你的API密钥");

  Future<void> _selectAddress() async {
    // 弹出地点选择界面
    Prediction? selectedPlace = await PlacesAutocomplete.show(
      context: context,
      apiKey: _apiKey,
      mode: Mode.overlay, // 可选全屏模式Mode.fullscreen
      language: "zh-CN",
      components: const [Component(Component.country, "cn")],
      hint: "请输入地址",
    );

    if (selectedPlace != null) {
      // 获取选中地点的详细信息
      PlacesDetailsResponse detail = await _places.getDetailsByPlaceId(selectedPlace.placeId!);
      // 更新输入框内容
      setState(() {
        _addressController.text = detail.result.name ?? "";
      });
      // 这里可以保存经纬度等信息
      double latitude = detail.result.geometry!.location.lat;
      double longitude = detail.result.geometry!.location.lng;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("地址输入")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: TextField(
          controller: _addressController,
          readOnly: true, // 让输入框只读,点击时触发选择逻辑
          onTap: _selectAddress,
          decoration: const InputDecoration(
            border: OutlineInputBorder(),
            hintText: "点击选择地址",
            suffixIcon: Icon(Icons.location_on),
          ),
        ),
      ),
    );
  }
}

3. 关键注意事项

  • API密钥安全:绝对不要把API密钥硬编码在代码里!Android可以通过local.properties配置,iOS用Info.plist管理,同时在Google Cloud控制台给密钥绑定应用的包名/指纹,进一步降低泄露风险。
  • 错误处理:一定要处理网络请求失败、API返回错误(比如密钥无效、请求次数超限)的情况,给用户显示友好的提示,比如“网络异常,请稍后重试”。
  • 用户体验优化:除了防抖,还可以在请求过程中显示加载动画,避免用户以为界面没反应;另外,建议列表的样式尽量和App整体风格统一,提升体验。

内容的提问来源于stack exchange,提问作者Gabe O'Leary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:09:39