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

Flutter如何实现Google Map选取地址并在组件中展示的功能

Flutter Google Map 地址选取功能实现方案

1. 前置依赖配置

首先在pubspec.yaml中添加所需依赖:

  • google_maps_flutter:用于Google地图渲染
  • geocoding:用于经纬度和实际地址的互转
  • 已配置好Google Cloud平台的Maps相关服务API密钥到Android/iOS项目中

2. 基础状态变量定义

在当前页面的State类中提前定义所需全局变量:

// 选中后展示的地址文本
String address = "";
// 地图控制器完成器
final Completer<GoogleMapController> _controller = Completer();
// 初始地图位置,示例为北京天安门坐标,可替换为自定义初始位置
static const CameraPosition _initialcameraposition = CameraPosition(
  target: LatLng(39.9042, 116.4074),
  zoom: 14.5,
);

3. 现有Widget逻辑补全

你现有代码中GoogleMap的onTap回调补全跳转地址选择页、接收返回结果转地址的逻辑:

Column(
  children: [
    Container(
      height: 200,
      width: double.infinity,
      child: GoogleMap(
        mapType: MapType.normal,
        initialCameraPosition: _initialcameraposition,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
        onTap: (LatLng location) async {
          // 跳转到地址选择页面,等待返回选中的经纬度
          final selectedLatLng = await Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const LocationPickerPage()),
          );
          if (selectedLatLng != null) {
            // 经纬度转实际地址文本
            List<Placemark> placemarks = await placemarkFromCoordinates(
              selectedLatLng.latitude,
              selectedLatLng.longitude,
            );
            if (placemarks.isNotEmpty) {
              Placemark place = placemarks.first;
              // 可根据业务需求调整地址拼接字段
              setState(() {
                address = "${place.country} ${place.administrativeArea} ${place.locality} ${place.street}";
              });
            }
          }
        },
      ),
    ),
    Text(address.isNotEmpty ? address : "请点击地图选择地址")
  ],
)

4. 地址选择页面实现

新建LocationPickerPage StatefulWidget,实现带搜索、标记功能的地址选择页:

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

  @override
  State<LocationPickerPage> createState() => _LocationPickerPageState();
}

class _LocationPickerPageState extends State<LocationPickerPage> {
  final Completer<GoogleMapController> _mapController = Completer();
  LatLng? _selectedLocation;
  final TextEditingController _searchController = TextEditingController();
  // 可复用初始位置常量,也可单独定义
  static const CameraPosition _initialPos = CameraPosition(
    target: LatLng(39.9042, 116.4074),
    zoom: 14.5,
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("选择地址"),
        actions: [
          IconButton(
            icon: const Icon(Icons.check),
            onPressed: _selectedLocation == null ? null : () {
              // 将选中的经纬度返回上一级页面
              Navigator.pop(context, _selectedLocation);
            },
          )
        ],
      ),
      body: Column(
        children: [
          // 地址搜索框
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              controller: _searchController,
              decoration: const InputDecoration(
                hintText: "输入地址搜索",
                prefixIcon: Icon(Icons.search),
                border: OutlineInputBorder(),
              ),
              onSubmitted: (value) async {
                if (value.trim().isEmpty) return;
                // 搜索地址转经纬度,移动地图到目标位置
                List<Location> locations = await locationFromAddress(value);
                if (locations.isNotEmpty) {
                  final target = LatLng(locations.first.latitude, locations.first.longitude);
                  final controller = await _mapController.future;
                  controller.animateCamera(CameraUpdate.newLatLngZoom(target, 16));
                  setState(() {
                    _selectedLocation = target;
                  });
                }
              },
            ),
          ),
          Expanded(
            child: GoogleMap(
              mapType: MapType.normal,
              initialCameraPosition: _initialPos,
              onMapCreated: (controller) => _mapController.complete(controller),
              onTap: (latLng) {
                // 点击地图选中位置,添加标记
                setState(() {
                  _selectedLocation = latLng;
                });
              },
              markers: _selectedLocation == null ? {} : {
                Marker(
                  markerId: const MarkerId("selected-location"),
                  position: _selectedLocation!,
                ),
              },
            ),
          ),
        ],
      ),
    );
  }
}

可选优化点

  • 可添加定位权限申请,默认定位到用户当前位置作为初始位置
  • 地址拼接规则可根据业务需求调整,比如增加邮编、门牌号等字段
  • 国内环境使用可替换为高德、百度等国内地图服务适配使用

内容的提问来源于stack exchange,提问作者Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 02:15:02