Android Map Custom Renderer在默认默认设置之上显示自定义渲染器

时间:2019-09-12 21:55:26

标签: android forms dictionary xamarin

我有一个使用Xamarin Form的跨平台应用程序,需要在地图上显示一堆自定义图钉。

我在这里遵循了该教程:https://docs.microsoft.com/it-it/xamarin/xamarin-forms/app-fundamentals/custom-renderer/map/customized-pin

在iOS上一切正常的情况下:

enter image description here

我在android上遇到了一些麻烦:

enter image description here

您可以看到自定义地图图钉显示在常规图钉上,这是自定义渲染器类:

  using System;
    using System.Collections.Generic;
    using Android.Content;
    using Android.Gms.Maps;
    using Android.Gms.Maps.Model;
    using Hangover.Droid.CustomRenderer;
    using Hangover.View;
    using Xamarin.Forms;
    using Xamarin.Forms.Maps;
    using Xamarin.Forms.Maps.Android;
    using Xamarin.Forms.Platform.Android;

    [assembly: ExportRenderer(typeof(map_mappaPersonalizzata), typeof(android_mappaPersonalizzata))]
    namespace Hangover.Droid.CustomRenderer
    {
        public class android_mappaPersonalizzata : MapRenderer
        {
            private static bool test = true;
            List<view_PinHangover> customPins;
            map_mappaPersonalizzata formsMap;

            public android_mappaPersonalizzata(Context context) : base(context)
            {

            }

            protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
            {
                base.OnElementChanged(e);

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

                if (e.NewElement != null)
                {
                    var crossMapPlatform = (map_mappaPersonalizzata)e.NewElement;
                    this.customPins = crossMapPlatform.datasource;
                    Control.GetMapAsync(this);
                }
            }



            /// <summary>
            /// Restituisce l'ID DI un pin in base al tipo
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            private int getPinID(String url)
            {
                if (url.Equals("drawable/map_clubBenefit.png"))
                    return Resource.Drawable.map_clubBenefit;
                else
                    return Resource.Drawable.map_club;

            }

            /// <summary>
            /// Metodo chiamato quando la mappa è pronta
            /// </summary>
            /// <param name="googleMap">Google map.</param>
            override protected void OnMapReady(GoogleMap googleMap)
            {
                base.OnMapReady(googleMap);

                formsMap = (map_mappaPersonalizzata)Element; // mappa cross platform
                var nativeMap = googleMap; // mappa nativa utilizzabile


                nativeMap.MyLocationEnabled = formsMap.IsShowingUser;
                nativeMap.InfoWindowClick += OnInfoWindowClick;

                var items = formsMap.datasource;

                foreach (var item in items)
                {
                    var markerWithIcon = new MarkerOptions();
                    markerWithIcon.SetPosition(new LatLng(item.evento.Lat, item.evento.Long));
                    markerWithIcon.SetTitle(item.evento.NomeEvento + " - " + item.evento.getPrezzo);
                    markerWithIcon.SetSnippet(item.getRating);

                    markerWithIcon.SetIcon(BitmapDescriptorFactory.FromResource(this.getPinID(item.icon)));

                    nativeMap.AddMarker(markerWithIcon);
                }

            }

            /// <summary>
            /// Gestisce la selezione di un elemento della mappa
            /// </summary>
            /// <param name="sender">Sender.</param>
            /// <param name="e">E.</param>
            void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
            {
                var customPin = getCustomPin(e.Marker);
                formsMap.gestisciOperazioneSchermata(customPin.evento); 
            }

            /// <summary>
            /// Ottiene il pin corrispondente a partire da una annotazione
            /// </summary>
            /// <returns>The custom pin.</returns>
            /// <param name="annotation">Annotation.</param>
            view_PinHangover 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;
            }
        }
    }

I'm really having trouble understanding why is rendered this way, 
thanks for the help.

**Edit**

So found the problem : in order to add the custom marker you have to override the method: 

    protected override MarkerOptions CreateMarker(Pin pin)

I was adding the custom marker in the wrong method and that caused the double pin on the map, so if Anyone is wondering , here is the full piece of code :

using System;
using System.Collections.Generic;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Hangover.Droid.CustomRenderer;
using Hangover.View;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(map_mappaPersonalizzata), typeof(android_mappaPersonalizzata))]
namespace Hangover.Droid.CustomRenderer
{
    public class android_mappaPersonalizzata : MapRenderer, GoogleMap.IInfoWindowAdapter
    {
        private static bool test = true;
        List<view_PinHangover> customPins;
        map_mappaPersonalizzata formsMap;

        public android_mappaPersonalizzata(Context context) : base(context)
        {

        }

        protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

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

            if (e.NewElement != null)
            {
                var crossMapPlatform = (map_mappaPersonalizzata)e.NewElement;
                this.customPins = crossMapPlatform.datasource;
                Control.GetMapAsync(this);
            }
        }


        /// <summary>
        /// Metodo chiamato quando la mappa è pronta
        /// </summary>
        /// <param name="googleMap">Google map.</param>
        override protected void OnMapReady(GoogleMap googleMap)
        {
            base.OnMapReady(googleMap);

            formsMap = (map_mappaPersonalizzata)Element; // mappa cross platform
            var nativeMap = googleMap; // mappa nativa utilizzabile

            nativeMap.SetInfoWindowAdapter(this);
            nativeMap.MyLocationEnabled = formsMap.IsShowingUser;
            nativeMap.InfoWindowClick += OnInfoWindowClick;

        }


        /// <summary>
        /// Crea il marker personalizzato sulla mappa cercando quello personalizzato
        /// nel datasource della mappa personalizzata
        /// </summary>
        /// <param name="pin"></param>
        /// <returns></returns>
        protected override MarkerOptions CreateMarker(Pin pin)
        {
            var marker = new MarkerOptions();

            var customMarker = getCustomPin(pin.Position.Latitude, pin.Position.Longitude);
            if (customMarker == null)
                return null;

            marker.SetPosition(new LatLng(customMarker.Position.Latitude, customMarker.Position.Longitude));
            marker.SetTitle(customMarker.evento.NomeEvento + " - " + customMarker.evento.getPrezzo);
            marker.SetSnippet(customMarker.getRating);
            marker.SetIcon(BitmapDescriptorFactory.FromResource(this.getPinID(customMarker.icon)));
            return marker;
        }

        /// <summary>
        /// Restituisce l'ID DI un pin in base al tipo
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private int getPinID(String url)
        {
            if (url.Equals("drawable/map_clubBenefit.png"))
                return Resource.Drawable.map_clubBenefit;
            else
                return Resource.Drawable.map_club;

        }

        /// <summary>
        /// Gestisce la selezione di un elemento della mappa
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">E.</param>
        void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
        {
            var customPin = getCustomPin(e.Marker.Position.Latitude,e.Marker.Position.Longitude);
            formsMap.gestisciOperazioneSchermata(customPin.evento); 
        }

        /// <summary>
        /// Ottiene il pin corrispondente a partire da una annotazione
        /// </summary>
        /// <returns>The custom pin.</returns>
        /// <param name="annotation">Annotation.</param>
        view_PinHangover getCustomPin(double lat,double longitude)
        {
            var position = new Position(lat, longitude);
            foreach (var pin in customPins)
            {
                if (pin.Position == position)
                {
                    return pin;
                }
            }
            return null;
        }

        public Android.Views.View GetInfoContents(Marker marker)
        {
            return null;
        }

        public Android.Views.View GetInfoWindow(Marker marker)
        {
            return null;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我可以尝试custom map,它可以正常工作,因此请按照以下代码修改您的代码。

 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;
    }