设置自定义标记图像将覆盖默认标记图标以及自定义图标

时间:2017-10-13 05:02:04

标签: android xamarin.forms maps marker

将表单版本更新到2.4.0.282后,我开始在MapView中获得这种奇怪的行为。我在android中为地图创建了一个自定义渲染器,我按照我的要求设置了标记图像。实际上会出现自定义标记,但最重要的是,它的默认图标仍然会被覆盖。

请注意,我使用的是Xamarin.Maps版本2.4.0.282,尝试降级到之前的版本,但我没有帮助。

我甚至通过评论行尝试了它,

  

Forms.SetFlags(" FastRenderers_Experimental&#34);

但即使这样也没有帮助。

以下是我创建的渲染器,

public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
    {
        GoogleMap map;

        public static double PreviousDistance = 0;

        List<CustomPin> customPins;

        CustomMap formsMap = null;

        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                map.InfoWindowClick -= OnInfoWindowClick;
                map.MarkerClick -= OnMarkerClick;
            }

            if (e.NewElement != null)
            {
                formsMap = (CustomMap)e.NewElement;
                customPins = formsMap.CustomPins;
                ((MapView)Control).GetMapAsync(this);
            }
        }

        protected override void OnMapReady(GoogleMap googleMap)
        {
            map = googleMap;
            map.InfoWindowClick += OnInfoWindowClick;

            map.MarkerClick += OnMarkerClick;

            map.UiSettings.ZoomControlsEnabled = false;

            formsMap.MoveToRegion(MapSpan.FromCenterAndRadius(formsMap.Location, Distance.FromMiles(1.0)));

            if(customPins != null && customPins.Count > 0)
            {
                setMapPins("CustomPins");
            }
        }

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == "CustomPins" || (e.PropertyName.Equals("VisibleRegion")))
            {
                setMapPins(e.PropertyName);
            }
        }

        private void setMapPins(string PropertyName)
        {
            customPins = formsMap.CustomPins;

            map.Clear();

            if (customPins != null && customPins.Count > 0)
            {
                if (PropertyName == "CustomPins")
                {
                    //Set map zoom
                    var defaultZoom = 14;

                    try
                    {
                        PreviousDistance = DistanceCalculation.MoveToRegionData.MoveToRegion(formsMap, customPins, defaultZoom, PreviousDistance);
                    }
                    catch (Exception ex)
                    {
                        PreviousDistance = 0;
                        Console.WriteLine(ex.Message);
                    }
                }

                foreach (var pin in customPins)
                {
                    var pinImage = Resources.GetIdentifier(pin.PinImage.ToLower(), "drawable", Context.PackageName);
                    var markerImg = BitmapDescriptorFactory.FromResource(pinImage);

                    map.AddMarker(new MarkerOptions().SetTitle(pin.Pin.Label).SetSnippet(pin.Id).SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude)).SetIcon(markerImg));
                }
            }
            else
            {
                Console.WriteLine("In else!!");
            }
        }

        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);

            if (changed)
            {
            }
        }

        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.Url))
            {
                var url = global::Android.Net.Uri.Parse(customPin.Url);
                var intent = new Intent(Intent.ActionView, url);
                intent.AddFlags(ActivityFlags.NewTask);
                global::Android.App.Application.Context.StartActivity(intent);
            }
        }

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

        void OnMarkerClick(object sender, GoogleMap.MarkerClickEventArgs ea)
        {   
            var marker = (Marker) ea.Marker;
            formsMap.IsPinClicked = false;

            var customPin = GetCustomPin(marker);
            if (customPin == null)
            {
                throw new Exception("Custom pin not found");
            }
            formsMap.SelectedPinId = Convert.ToInt32(marker.Snippet);
            formsMap.IsPinClicked = true;
        }
    }

这就是它现在的样子..

enter image description here

2 个答案:

答案 0 :(得分:1)

  

我在android中为地图创建了一个自定义渲染器,我根据自己的要求设置了标记图像。事实上,自定义标记会出现,但除此之外,它的默认图标仍会被覆盖。

我做了一个演示并重现了这个问题,经过一些测试我发现OnMapReady函数的覆盖导致了问题。即使完全为空OnMapReady,也会出现问题。我的猜测是调用自定义地图渲染中的OnMapReady可能会导致重新渲染包含图钉的地图。

<强>解决方案:

  1. 评论OnMapReady
  2. OnMapReady中的逻辑移至OnElementChanged
  3. 让您的本地变量map=NativeMap并确保在setMapPins中调用OnElementPropertyChanged

答案 1 :(得分:1)

OnElementPropertyChanged 中添加 NativeMap.Clear(); ,然后重试。希望它会有所帮助!!!

在Android平台上查看以下用于自定义PIN码的代码。

[assembly:ExportRenderer (typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.Droid
{
    public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
    {
        List<CustomPin> customPins;
        bool isDrawn;

        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<View> e)
        {
            base.OnElementChanged(e);

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

            if (e.NewElement != null)
            {
                var formsMap = (CustomMap)e.NewElement;
                customPins = formsMap.CustomPins;
                ((MapView)Control).GetMapAsync(this);
            }
        }


        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
            {
                NativeMap.Clear();
                NativeMap.InfoWindowClick += OnInfoWindowClick;
                NativeMap.SetInfoWindowAdapter(this);

                foreach (var pin in customPins)
                {
                    var marker = new MarkerOptions();
                    marker.SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude));
                    marker.SetTitle(pin.Pin.Label);
                    marker.SetSnippet(pin.Pin.Address);
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));

                    NativeMap.AddMarker(marker);
                }
                isDrawn = true;
            }
        }
    }

}

详细信息Click here