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

Flutter谷歌地图多位置添加自定义Marker图标不生效问题求助

问题原因
  • 参数传递逻辑错误:Dart的函数参数是值传递,你定义的setCustomMarker函数中,给形参mapMarker赋值仅会修改该形参的局部副本,不会同步修改类的成员变量mapMarker1、mapMarker2。相当于你加载好的自定义图标根本没有存到后续要使用的变量中,使用时变量为null,谷歌地图就会自动 fallback 到默认标记图标。
  • 异步时序问题:setCustomMarker是异步函数,你在initState中直接调用后没有等待加载完成,页面渲染GoogleMap组件时,图标还未加载完毕,markers集合中的icon属性仍然是null,自然显示默认图标。
修复方案
  1. 改造setCustomMarker函数,直接返回加载完成的BitmapDescriptor对象,而不是尝试通过形参赋值:
Future<BitmapDescriptor> setCustomMarker(String iconPath) async {
  return await BitmapDescriptor.fromAssetImage(
    ImageConfiguration.empty,
    iconPath,
  );
}
  1. 合并图标加载和接口请求为一个异步任务,确保所有资源加载完成后再渲染地图:
class _SafeSheltersPageState extends State<SafeSheltersPage> {
  late Future _loadAllDataFuture;

  Future<Map> _loadAllRequiredData() async {
    // 用Future.wait同时执行图标加载和接口请求,提升效率
    final asyncResults = await Future.wait([
      setCustomMarker('images/map/user_location.png'),
      setCustomMarker('images/map/safe_shelter.png'),
      _sheltersFutureBuilder(), // 你原有定义的接口请求方法
    ]);
    return {
      'userMarker': asyncResults[0] as BitmapDescriptor,
      'shelterMarker': asyncResults[1] as BitmapDescriptor,
      'apiData': asyncResults[2],
    };
  }

  // 你原有代码的sheltersFutureBuilder方法,可以保留不动,重命名为私有更规范
  Future _sheltersFutureBuilder() async {
    CurrentLocation currentLocation = await CurrentLocationUtil().getLocation();
    Map<String, Object> data = {
      'location': {
        'latitude': currentLocation.latitude,
        'longitude': currentLocation.longitude,
      }
    };
    return CallApi().postData(data, 'public/api/getShelterLocations');
  }

  @override
  void initState() {
    super.initState();
    _loadAllDataFuture = _loadAllRequiredData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Safe Shelters'),
        centerTitle: true,
        backgroundColor: Colors.red.shade300,
      ),
      body: SafeArea(
        child: FutureBuilder(
          future: _loadAllDataFuture,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
              final resultMap = snapshot.data as Map;
              final apiResponse = resultMap['apiData'];
              String responseBody = apiResponse.body;
              var data = jsonDecode(responseBody);
   
              double userCurrentLatitude = data['current_loc']['latitude'];
              double userCurrentLongitude = data['current_loc']['longitude'];

              double nearestShelterLat = double.parse(data['shelters']['nearest_shelter'][0]['latitude']);
              double nearestShelterLon = double.parse(data['shelters']['nearest_shelter'][0]['longitude']);

              final Set<Marker> markers = {
                Marker(
                  markerId: const MarkerId("user-loc"),
                  position: LatLng(userCurrentLatitude, userCurrentLongitude),
                  icon: resultMap['userMarker'] as BitmapDescriptor,
                  infoWindow: const InfoWindow(
                    title: 'You',
                    snippet: 'You are currently here!',
                  ),
                ),
                Marker(
                  markerId: const MarkerId("nearest-shelter"),
                  position: LatLng(nearestShelterLat, nearestShelterLon),
                  icon: resultMap['shelterMarker'] as BitmapDescriptor,
                  infoWindow: const InfoWindow(
                    title: 'Nearest Safe Shelter',
                    snippet: 'This is the nearest safe shelter from your location',
                  ),
                ),
              };

              return GoogleMap(
                markers: markers,
                initialCameraPosition: CameraPosition(
                  target: LatLng(userCurrentLatitude, userCurrentLongitude),
                  zoom: 15,
                ),
              );
            }
            // 建议加上加载中的占位组件
            return const Center(child: CircularProgressIndicator());
          },
        ),
      ),
    );
  }
}

可选优化

如果出现图标大小在不同设备上显示异常的问题,可以在加载图标时传入设备像素比:

Future<BitmapDescriptor> setCustomMarker(String iconPath) async {
  return await BitmapDescriptor.fromAssetImage(
    ImageConfiguration(
      devicePixelRatio: WidgetsBinding.instance.window.devicePixelRatio
    ),
    iconPath,
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:45:05