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

Flutter实现点击按钮获取当前位置并在OpenStreetMap添加标记

实现Flutter地图点击按钮定位当前位置并添加红色标记

问题描述

我想在Flutter项目的按钮中添加功能:点击按钮时,OpenStreetMap显示我的当前位置并添加红色标记。现有代码如下:

现有页面代码

import 'package:geocoding/geocoding.dart'; // Package maps
import 'package:geolocator/geolocator.dart'; // Package maps
import 'package:flutter_map/flutter_map.dart'; // Package maps
import 'package:latlong2/latlong.dart'; // Package maps

class _AbsenPageState extends State<AbsenPage> {
  Position? _currentLocation;
  bool servicePermission = false;
  LocationPermission permission = LocationPermission.denied;
  String _currentAddress = "";
  bool showSyncText = true; // 控制"点击图标同步"文本的显示

  Future<Position> _getCurrentLocation() async {
    servicePermission = await Geolocator.isLocationServiceEnabled();
    if (!servicePermission) {
      print("Service Disabled");
    }
    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
    }
    return await Geolocator.getCurrentPosition();
  }

  _getAddressFromCoordinates() async {
    try {
      List<Placemark> placemarks = await placemarkFromCoordinates(
        _currentLocation!.latitude,
        _currentLocation!.longitude,
      );

      Placemark place = placemarks[0];

      setState(() {
        _currentAddress = "${place.street}";
        showSyncText = false; // 获取到地址后隐藏提示文本
      });
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: [
          FlutterMap(
            options: const MapOptions(
              center: LatLng(-7.238141, 112.734710),
              zoom: 18.0,
            ),
            children: [
              TileLayer(
                urlTemplate:
                'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                subdomains: const ['a', 'b', 'c'],
              ),

            ],
          ),

现有按钮代码

ElevatedButton(
  onPressed: () async {
    _currentLocation = await _getCurrentLocation();
    await _getAddressFromCoordinates();
    print("$_currentAddress");
  },
),

解决方案

要实现点击按钮定位并添加红色标记的功能,需要做以下3处修改:

  • 添加标记图层:在FlutterMap的子组件中加入MarkerLayer,根据当前位置生成红色标记
  • 动态切换地图中心:当获取到当前位置后,自动将地图中心定位到该位置
  • 触发UI刷新:获取位置后调用setState,让地图更新标记和中心坐标

修改后的关键代码

1. 更新FlutterMap组件

FlutterMap(
  options: MapOptions(
    // 有当前位置时用当前坐标作为中心,否则用默认值
    center: _currentLocation != null 
        ? LatLng(_currentLocation!.latitude, _currentLocation!.longitude) 
        : const LatLng(-7.238141, 112.734710),
    zoom: 18.0,
  ),
  children: [
    TileLayer(
      urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      subdomains: const ['a', 'b', 'c'],
    ),
    // 只有获取到位置后才显示标记
    if (_currentLocation != null)
      MarkerLayer(
        markers: [
          Marker(
            width: 80.0,
            height: 80.0,
            point: LatLng(_currentLocation!.latitude, _currentLocation!.longitude),
            builder: (ctx) => const Icon(
              Icons.location_on,
              color: Colors.red,
              size: 40.0,
            ),
          ),
        ],
      ),
  ],
),

2. 更新按钮的onPressed方法

ElevatedButton(
  onPressed: () async {
    _currentLocation = await _getCurrentLocation();
    await _getAddressFromCoordinates();
    // 刷新UI,让地图更新中心和标记
    setState(() {});
    print("$_currentAddress");
  },
),

说明

  • 点击按钮后,程序会先检查位置权限、获取当前位置,然后地图会自动跳转到你的位置并显示红色定位图标
  • 如果需要自定义标记样式,可以修改Marker的builder部分,比如替换成自定义图片或容器组件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 15:57:55