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

Flutter中Google Maps实现用户移动时实时更新位置及路线

解决方案

要实现用户移动时实时更新位置Marker和路线Polyline,你需要对现有代码做以下几处关键修改,核心是监听位置实时变化并同步更新地图元素:

核心修改要点

  • 启用位置服务的实时监听,替换一次性获取位置的逻辑
  • 优化Marker更新:每次更新用户位置时,移除旧的用户Marker再添加新的,避免重复创建
  • 优化Polyline更新:每次获取新路线前清空旧坐标,确保路线是最新的
  • 提前处理位置权限,保证能正常获取位置数据
  • 静态目的地Marker只初始化一次,避免重复添加

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'package:custom_marker/marker_icon.dart';
import 'package:flutter/services.dart' show rootBundle;

import 'CustomMarker.dart';

class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  GoogleMapController? _controller;
  final GlobalKey myglobalKey = GlobalKey();
  final GlobalKey otherglobalKey = GlobalKey();
  Set<Marker> _markers = {};
  List<LatLng> polylineCoordinates = [];
  late String _mapStyle;
  late Location _location;
  LocationData? _currentLocation;
  // 静态目的地坐标
  final LatLng _destination = LatLng(28.4212, 70.2989);

  @override
  void initState() {
    super.initState();
    _initLocationService();
    _loadMapStyle();
    // 初始化静态目的地Marker(只执行一次)
    _initDestinationMarker();
  }

  // 初始化位置服务并启动监听
  Future<void> _initLocationService() async {
    _location = Location();
    // 检查位置权限
    bool serviceEnabled;
    PermissionStatus permissionGranted;

    serviceEnabled = await _location.serviceEnabled();
    if (!serviceEnabled) {
      serviceEnabled = await _location.requestService();
      if (!serviceEnabled) return;
    }

    permissionGranted = await _location.hasPermission();
    if (permissionGranted == PermissionStatus.denied) {
      permissionGranted = await _location.requestPermission();
      if (permissionGranted != PermissionStatus.granted) return;
    }

    // 获取初始位置
    _currentLocation = await _location.getLocation();
    if (_currentLocation != null) {
      await _updateUserMarker();
      await _updatePolyline();
      _moveCameraToUser();
    }

    // 监听位置变化
    _location.onLocationChanged.listen((LocationData newLocation) {
      setState(() {
        _currentLocation = newLocation;
      });
      _updateUserMarker();
      _updatePolyline();
      // 可选:是否跟随用户位置自动移动相机,取消注释即可开启
      // _moveCameraToUser();
    });
  }

  // 加载地图样式
  void _loadMapStyle() {
    rootBundle.loadString('assets/mapStyle.txt').then((string) {
      setState(() {
        _mapStyle = string;
        _controller?.setMapStyle(_mapStyle);
      });
    });
  }

  // 初始化目的地Marker
  Future<void> _initDestinationMarker() async {
    final destinationIcon = await MarkerIcon.widgetToIcon(otherglobalKey);
    setState(() {
      _markers.add(
        Marker(
          icon: destinationIcon,
          markerId: const MarkerId('Destination'),
          position: _destination,
        ),
      );
    });
  }

  // 更新用户位置Marker
  Future<void> _updateUserMarker() async {
    if (_currentLocation == null) return;
    final userIcon = await MarkerIcon.widgetToIcon(myglobalKey);
    // 先移除旧的用户Marker,避免重复显示
    _markers.removeWhere((marker) => marker.markerId.value == 'MyLocation');
    setState(() {
      _markers.add(
        Marker(
          icon: userIcon,
          markerId: const MarkerId('MyLocation'),
          position: LatLng(
            _currentLocation!.latitude ?? 0.0,
            _currentLocation!.longitude ?? 0.0,
          ),
        ),
      );
    });
  }

  // 更新路线Polyline
  Future<void> _updatePolyline() async {
    if (_currentLocation == null) return;
    PolylinePoints polylinePoints = PolylinePoints();
    PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
      "AIzaSyBI22C6hc7_C4yRuyEnUPHPJGu3k0GH6PU",
      PointLatLng(
        _currentLocation!.latitude ?? 0.0,
        _currentLocation!.longitude ?? 0.0,
      ),
      PointLatLng(_destination.latitude, _destination.longitude),
    );
    if (result.points.isNotEmpty) {
      setState(() {
        // 清空旧路线坐标,添加新的路线点
        polylineCoordinates.clear();
        result.points.forEach((PointLatLng point) =>
            polylineCoordinates.add(LatLng(point.latitude, point.longitude)));
      });
    }
  }

  // 移动相机到用户位置
  void _moveCameraToUser() {
    if (_currentLocation == null) return;
    _controller?.animateCamera(
      CameraUpdate.newCameraPosition(
        CameraPosition(
          target: LatLng(
            _currentLocation!.latitude ?? 0.0,
            _currentLocation!.longitude ?? 0.0,
          ),
          zoom: 12.0,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Map"),
        backgroundColor: Theme.of(context).scaffoldBackgroundColor,
      ),
      body: Stack(
        children: [
          MyMarker(myglobalKey),
          OtherUserMarker(otherglobalKey),
          SizedBox(
            height: MediaQuery.of(context).size.height,
            width: MediaQuery.of(context).size.width,
            child: GoogleMap(
              zoomControlsEnabled: false,
              initialCameraPosition: const CameraPosition(
                target: LatLng(0, 0),
                zoom: 12.0,
              ),
              onMapCreated: (GoogleMapController controller) {
                _controller = controller;
                if (_mapStyle.isNotEmpty) {
                  _controller?.setMapStyle(_mapStyle);
                }
              },
              markers: _markers,
              polylines: {
                Polyline(
                  polylineId: const PolylineId("route"),
                  points: polylineCoordinates,
                  color: const Color(0xFF7B61FF),
                  width: 6,
                ),
              },
            ),
          ),
        ],
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
      floatingActionButton: FloatingActionButton(
        onPressed: _moveCameraToUser,
        backgroundColor: Theme.of(context).scaffoldBackgroundColor,
        child: const Icon(Icons.location_searching_rounded,
            color: Colors.white, size: 20),
      ),
    );
  }
}

关键修改解释

  1. 位置实时监听:通过_location.onLocationChanged.listen()持续监听用户位置变化,一旦位置更新就触发Marker和路线的更新
  2. Marker去重逻辑:每次更新用户位置时,先移除旧的用户Marker,再添加新的,避免地图上出现多个用户位置标记
  3. 路线更新优化:每次获取新路线前清空旧坐标列表,确保显示的是从当前位置到目的地的最新路线
  4. 权限前置处理:初始化位置服务时先检查并请求位置权限和服务,避免因权限问题导致无法获取位置数据
  5. 静态Marker复用:目的地Marker只在初始化时创建一次,不需要重复添加
  6. 相机控制可选:保留了浮动按钮用于手动定位用户位置,同时提供了自动跟随的注释代码,可按需开启

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 18:56:23