Xamarin Forms - 自定义地图标记不可见

Posted

技术标签:

【中文标题】Xamarin Forms - 自定义地图标记不可见【英文标题】:Xamarin Forms - custom map marker not visible 【发布时间】:2021-10-19 22:08:02 【问题描述】:

我正在关注 MS 页面上关于 Custom map renderer 的文章,但我无法让它在 android 上工作。地图显示,但大头针(标记)不存在。我没有发现我所做的与官方文件有什么不同(如上一个链接)。当我调试时,customPins 集合中有 3 个标记。自定义渲染器适用于 UWP。所以问题只存在于 Android 代码中。

这是我用于 Android 的 CustomRender 代码,它不显示图钉。

using System;
using System.Collections.Generic;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using iVanApp;
using iVanApp.Android.CustomMapRenderers;
using iVanApp.Droid;
using iVanApp.Model;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;

[assembly: ExportRenderer(typeof(NightMap), typeof(MapRenderers))]

namespace iVanApp.Android.CustomMapRenderers

    public class MapRenderers : MapRenderer, GoogleMap.IInfoWindowAdapter
    
        List<NightPin> customPins;

        public MapRenderers(Context context) : base(context)
        
        
        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
        
            base.OnElementChanged(e);

            if (e.OldElement != null)
            
                NativeMap.InfoWindowClick -= OnInfoWindowClick;
            

            if (e.NewElement != null)
            
                var formsMap = (NightMap)e.NewElement;
                customPins = formsMap.NightPins;
            
        
        protected override void OnMapReady(GoogleMap map)
        
            base.OnMapReady(map);

            NativeMap.InfoWindowClick += OnInfoWindowClick;
            
            NativeMap.SetInfoWindowAdapter(this);
        

        protected override MarkerOptions CreateMarker(Pin pin)
        
            var marker = new MarkerOptions();
            marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
            marker.SetTitle(pin.Label);
            marker.SetSnippet(pin.Address);
            marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
            
            return marker;
        
        void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
        
            var customPin = GetCustomPin(e.Marker);
            if (customPin == null)
            
                throw new Exception("Custom pin not found");
            

            if (!string.IsNullOrWhiteSpace(customPin.Name))
            

            
        



        NightPin GetCustomPin(Marker annotation)
        
            var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);
            foreach (var pin in customPins)
            
                if (pin.Position == position)
                
                    return pin;
                
            
            return null;
        

        public global::Android.Views.View GetInfoContents(Marker marker)
        
            var inflater = global::Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as global::Android.Views.LayoutInflater;
            if (inflater != null)
            
                global::Android.Views.View view;

                var customPin = GetCustomPin(marker);
                if (customPin == null)
                
                    throw new Exception("Custom pin not found");
                
                view = inflater.Inflate(Resource.Layout.mtrl_layout_snackbar_include, null);
                if (customPin.Name.Equals("Xamarin"))
                
                    view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null);
                
                else
                
                    view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
                

                var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
                var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);

                if (infoTitle != null)
                
                    infoTitle.Text = marker.Title;
                
                if (infoSubtitle != null)
                
                    infoSubtitle.Text = marker.Snippet;
                

                return view;
            
            return null;
        

        public global::Android.Views.View GetInfoWindow(Marker marker)
        
            return null;
        


    

有人知道为什么这不起作用吗?

注意:由于出现错误,我不得不修改官方 MS 代码。无论Android.Views.View在哪里,我都必须将其修改为global::Android.Views.View,否则会出现以下错误

"'MapRenderers' 没有实现接口成员 'GoogleMap.IInfoWindowAdapter.GetInfoContents(标记)'。 'MapRenderers.GetInfoContents(Marker)' 无法实现 'GoogleMap.IInfoWindowAdapter.GetInfoContents(Marker)' 因为它确实 没有匹配的“视图”返回类型。”。

命名空间中不存在类型或命名空间名称“Views” 'iVanApp.Android'(您是否缺少程序集引用?)

希望这不会破坏我的代码。

在调查和阅读其他人的自定义地图问题(主要是解决方案)后,我得到了一个解决方法,即如何在地图上获取图钉,但当我点击图钉(标记)时不显示信息窗口。 Here I found workaround。如果我修改 OnMapReday 并调用和添加方法 SetMapMarkers 则引脚可见,但正如我所说,当我单击引脚时没有显示任何信息窗口

protected override void OnMapReady(GoogleMap map)
    
        base.OnMapReady(map);

        NativeMap.InfoWindowClick += OnInfoWindowClick;
        
        NativeMap.SetInfoWindowAdapter(this);
        SetMapMarkers();
           

private void SetMapMarkers()
        
            NativeMap.Clear();

            foreach (var pin in customPins)
            
                NativeMap.AddMarker(CreateMarker(pin));
            
        

虽然这是一个解决方案,但如果我能在没有这种解决方法的情况下让它工作,我会更喜欢。因此,我没有付出太多努力,为什么单击 pin 时不显示信息窗口。如果没有这种解决方法就没有解决方案,那么我会对有解决方法的解决方案感兴趣,但正如我所说,我不喜欢这样。

【问题讨论】:

在您的旧代码中,我没有看到您在地图上添加图钉是故意的吗?我错过了什么吗? 既然你提到了这一点,我也注意到了。在提供的官方文档和示例中,没有将引脚添加到地图的代码。因此我虽然这不是必需的。并且仅在 UWP 示例中对此进行了调查后,有代码可以将引脚添加到地图。奇怪的是没有Android和ios的代码,还是我遗漏了什么?在我添加代码后,您提到图钉在地图上。因此,如果您将其写为答案,我可以将其标记为正确的答案。 【参考方案1】:

正如 FreakyAli 所说,为 CustomMap 添加自定义图钉和位置。

  <local:CustomMap x:Name="customMap" MapType="Street" />

添加自定义图钉并使用 MoveToRegion 方法定位地图视图

 public  MainPage()
    
        InitializeComponent();
        var pin = new CustomPin
        
            Type = PinType.Place,
            Position = new Position(37.79752, -122.40183),
            Label = "Xamarin San Francisco Office",
            Address = "394 Pacific Ave, San Francisco CA",
            Id = "Xamarin",
            Url = "http://xamarin.com/about/"
        ;

        customMap.CustomPins = new List<CustomPin>  pin ;
        customMap.Pins.Add(pin);
        customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.79752, -122.40183), Distance.FromMiles(1.0)));

    

我可以通过点击地图图钉获得InfoWindow,没有问题。

【讨论】:

以上是关于Xamarin Forms - 自定义地图标记不可见的主要内容,如果未能解决你的问题,请参考以下文章

如何居中/设置地图缩放以覆盖 Xamarin.Forms 上可见的所有标记?

如何在 Xamarin Forms 中实现标记聚类(谷歌地图)

有没有办法动画Xamarin.Forms.Maps针运动

Xamarin.Forms 不可点击的 ListView(移除选择涟漪效应)

Xamarin.Forms 使用 Flyout/Menu Item 作为标题并自定义 BG 颜色和文本颜色

Xamarin.Forms自定义GridView