Xamarin Forms Custom Map Pin

怎甘沉沦 提交于 2019-12-01 13:47:39

First of all I would like to provide 2 links that helped me to understand the problem. Thank you guys. Xamarin.Forms.Maps 2.3.4 custom MapRenderer disables everything and https://forums.xamarin.com/discussion/92565/android-ionmapreadycallback-forms-2-3-4

Latest Xamarin Maps broke OnElementPropertyChanged with VisibleRegion. They defined that MapRenderer now implements IOnMapReadyCallback and that broke somehow OnElementPropertyChanged (I didn't investigate how and why). As you can see in link I provided there are 2 methods you can go. To keep your renderer implementing IOnMapReadyCallback or not. When I kept IOnMapReadyCallback I started to get 2 pins - one of top another - our custom pin and regular pin. I didn't dig more how that happens and removed IOnMapReadyCallback. After that things became really simple because if you let Xamarin handle it and create NativeMap you can remove some code and make renderer simpler.

Before I post the code I also want to mention that when I fixed it the app started crashing with OutOfMemory exception and I found out that your pin image is 2000 pixels width. I changed it to 40. Below is the code:

public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter//, IOnMapReadyCallback
{
    bool isDrawn;

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

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

    }


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

        if (!isMapReady && (NativeMap != null))
        {
            NativeMap.SetInfoWindowAdapter(this);
            NativeMap.InfoWindowClick += OnInfoWindowClick;
            isMapReady = true;
        }

        if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
        {
            NativeMap.Clear();

            foreach (var pin in ((CustomMap)Element).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;
        }
    }

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

        if (changed)
        {
            isDrawn = false;
        }
    }

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

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

            var customPin = GetCustomPin(marker);
            if (customPin == null)
            {
                throw new Exception("Custom pin not found");
            }

            if (customPin.Id == "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 Android.Views.View GetInfoWindow(Marker marker)
    {
        return null;
    }

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


}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!