Xamarin Forms Android端自定义地图标记(Marker)不显示问题求助
根因分析
不使用workaround时标记不显示的原因
- Xamarin.Forms 原生的
MapRenderer只会自动渲染基类Map自带的Pins集合中的元素,你自定义的NightMap.NightPins属于自定义集合,没有纳入原生渲染器的自动渲染流程,所以哪怕customPins里有数据也不会自动生成Marker。 - 你之前修改的
global::Android.Views.View命名空间前缀只是解决命名空间冲突,和标记不显示没有关联。
使用workaround后信息窗口不显示的原因
- 你通过坐标匹配
NightPin的逻辑存在精度问题:经纬度是double类型,存储和渲染时的微小精度误差会导致GetCustomPin返回null,触发异常后信息窗口无法正常加载。 - 你
GetInfoContents方法中第一行多余加载了mtrl_layout_snackbar_include布局,后续才覆盖为实际的信息窗口布局,可能存在布局加载异常。 - 部分场景下手动添加的Marker不会默认触发信息窗口弹出逻辑,需要手动处理点击事件。
解决方案
方案1:无需workaround的标准实现(推荐)
- 调整自定义
NightMap的逻辑,将NightPins改为ObservableCollection<NightPin>类型,监听集合变化,同步将元素同步到基类Map.Pins集合,触发原生自动渲染:
public class NightMap : Map { public ObservableCollection<NightPin> NightPins { get; } = new ObservableCollection<NightPin>(); public NightMap() { NightPins.CollectionChanged += (s, e) => { if (e.NewItems != null) { foreach (NightPin pin in e.NewItems) { Pins.Add(pin); } } if (e.OldItems != null) { foreach (NightPin pin in e.OldItems) { Pins.Remove(pin); } } }; } }
- 确保
NightPin直接继承自Xamarin.Forms.Maps.Pin,保证类型兼容。 - 删掉你新增的
SetMapMarkers方法和调用逻辑,原生渲染器会自动调用你重写的CreateMarker方法生成自定义标记,同时信息窗口逻辑也会正常生效。
方案2:修复现有workaround的信息窗口问题
如果要保留手动添加Marker的逻辑,按以下步骤修改:
- 新增Marker映射字典,替换坐标匹配逻辑,避免精度问题:
private Dictionary<Marker, NightPin> _markerLookup = new Dictionary<Marker, NightPin>(); private void SetMapMarkers() { NativeMap.Clear(); _markerLookup.Clear(); foreach (var pin in customPins) { var marker = NativeMap.AddMarker(CreateMarker(pin)); _markerLookup.Add(marker, pin); } } NightPin GetCustomPin(Marker annotation) { _markerLookup.TryGetValue(annotation, out var pin); return pin; }
- 删掉
GetInfoContents方法中多余的布局加载代码:
// 删掉这行多余代码 // view = inflater.Inflate(Resource.Layout.mtrl_layout_snackbar_include, null);
- 监听Marker点击事件,手动弹出信息窗口:
protected override void OnMapReady(GoogleMap map) { base.OnMapReady(map); NativeMap.InfoWindowClick += OnInfoWindowClick; NativeMap.SetInfoWindowAdapter(this); // 新增Marker点击监听 NativeMap.MarkerClick += (s, e) => { e.Marker.ShowInfoWindow(); e.Handled = true; }; SetMapMarkers(); }
- 确保所有
NightPin的Label和Address属性都已赋值,谷歌地图默认不会为空内容的Marker弹出信息窗口。
内容的提问来源于stack exchange,提问作者Bumbar
相关产品推荐
相关产品推荐

