Flutter 谷歌地图视图无法显示多个自定义标记图标如何解决
问题修复方案
你遇到的问题主要由以下几个错误导致,按优先级修复即可:
核心问题:所有Marker的ID重复
谷歌地图的Marker要求每个markerId必须全局唯一,且Set<Marker>会根据markerId自动去重,你所有标记都用了MarkerId('SomeId'),会导致添加的标记互相覆盖,最终Set里可能只剩1个不在视野范围内的标记,看起来就像全部不显示。
次要问题:异步操作未触发UI刷新
setCustomMarkers是异步方法,加载图标、添加标记完成后没有调用setState通知界面刷新,地图拿到的还是初始化时的空标记列表。
其他问题
- 公交图标资源路径写错,你原来的代码里加载公交图标时用了train.png的路径
- FutureBuilder每次重绘都会重复往
_markers里添加旅游点标记,导致列表冗余
具体修复步骤
- 给所有Marker分配唯一ID,不管是自定义交通图标,还是旅游点标记,都用唯一标识作为markerId
- 异步加载完成后调用
setState刷新界面 - 修复资源路径,避免重复添加标记
修复后的核心代码参考
// 修改setCustomMarkers方法 Future<void> setCustomMarkers() async { BitmapDescriptor portIcon, busIcon, trainIcon; final Uint8List markerIconPort = await getBytesFromAsset('assets/images/port.png', 100); final Uint8List markerIconTrain = await getBytesFromAsset('assets/images/train.png', 100); // 修复公交图标路径 final Uint8List markerIconBus = await getBytesFromAsset('assets/images/bus.png', 100); portIcon = BitmapDescriptor.fromBytes(markerIconPort); trainIcon = BitmapDescriptor.fromBytes(markerIconTrain); busIcon = BitmapDescriptor.fromBytes(markerIconBus); // 给每个marker分配唯一ID _markers.add(Marker( markerId: MarkerId('port_1'), position: LatLng(40.672842, 14.769194), infoWindow: InfoWindow(title: "Port 1"), icon: portIcon, )); _markers.add(Marker( markerId: MarkerId('port_2'), position: LatLng(40.674126, 14.752421), infoWindow: InfoWindow(title: "Port 2"), icon: portIcon, )); _markers.add(Marker( markerId: MarkerId('train_1'), position: LatLng(40.675804, 14.772802), infoWindow: InfoWindow(title: "Train"), icon: trainIcon, )); _markers.add(Marker( markerId: MarkerId('bus_1'), position: LatLng(40.674102, 14.776989), infoWindow: InfoWindow(title: "Bus"), icon: busIcon, )); // 加载完成后刷新UI if(mounted) setState(() {}); } // 修改FutureBuilder里的旅游点标记添加逻辑,避免重复添加,同时设置唯一ID if (turisticPointList.isNotEmpty) { // 先移除旧的旅游点标记,避免重复添加 _markers.removeWhere((marker) => marker.markerId.value.startsWith('turistic_')); for (int i = 0; i < turisticPointList.length; i++) { _markers.add(Marker( markerId: MarkerId('turistic_$i'), position: LatLng( double.parse(turisticPointList[i].latitudine), double.parse(turisticPointList[i].longitudine)), infoWindow: InfoWindow( title: AppLocalizations.of(context) .translate(turisticPointList[i].titolo), ))); } } // iOS尺寸适配优化:getBytesFromAsset方法可以根据设备像素比动态调整尺寸 Future<Uint8List> getBytesFromAsset(String path, int width) async { // 适配iOS不同分辨率屏幕,按设备像素比缩放尺寸 double pixelRatio = MediaQuery.of(context).devicePixelRatio; int targetWidth = (width * pixelRatio).round(); ByteData data = await rootBundle.load(path); ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: targetWidth); ui.FrameInfo fi = await codec.getNextFrame(); return (await fi.image.toByteData(format: ui.ImageByteFormat.png)) .buffer .asUint8List(); }
内容的提问来源于stack exchange,提问作者TheOldBlackbeard
相关产品推荐
相关产品推荐

