How to add multiple different custom icons on Xamarin Forms Maps?

I’m trying to render a map with multiple different custom map pins.

I have managed to replace all my icons to a custom icon following the documentation provided here:

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/map-pin

However what I wish to achieve is to change the icon based on a property value off my CustomPin class, the problem seems to be that when rendering my map, the markers get created but my CustomPin List is still “null”, I’ve tried to find more documentation or answers about multiple icons based on a custom property without success.

Could anyone give me a push in the right direction?

Code snippets, which are currently not working as stated above:

CustomPin

    public class CustomPin : Pin
    {
        public string IconType { get; set; }
    }

CustomMap

     public class CustomMap : Map
    {
        public List<CustomPin> CustomPins { get; set; }
    }

MapPage.xaml.cs (populating the pin lists => IconType is my custom property to check which icon to render)

    private void DisplayOnMap(IList<Models.Location> pins)
        {
            List<CustomPin> CustomPins = new List<CustomPin>();
            foreach (var item in pins)
            {
                try
                {
                    var position = new Xamarin.Forms.Maps.Position(item.lat, item.lon);
                    var pin = new CustomPin()
                    {
                        Type = Xamarin.Forms.Maps.PinType.Generic,
                        Position = position,
                        Label = item.naam,
                        Address = $"{item.straat} {item.nummer}, {item.postnr} {item.stad} ({item.land})",
                        IconType = item.soort
                    };
                    CustomPins.Add(pin);
                }
                catch (NullReferenceException nre)
                {
                    Console.WriteLine(nre.Message);
                }
                catch (Exception ex)
                {

                }
            }
            locationsMap.CustomPins = CustomPins;
            foreach (var cpin in locationsMap.CustomPins)
            {
                locationsMap.Pins.Add(cpin);
            }
        }

CustomRenderer (Android)

    public class CustomMapRenderer : MapRenderer
    {
        List<CustomPin> customPins;
        public CustomMapRenderer(Context context) : base(context)
        {
        }

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

            if (e.OldElement != null)
            {
            }

            if (e.NewElement != null)
            {
                
            }
        }
        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);
            var customPin = GetCustomPin(pin);
            if (customPin != null)
            {
                if(customPin.IconType == "corporate")
                {
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.corporate));
                }
                else if(customPin.IconType == "pickup")
                {
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.bus));
                } 
            }
           
            return marker;
        }


        CustomPin GetCustomPin(Pin pin)
        {
            var position = pin.Position;
            foreach (var cpin in customPins)
            {
                if (cpin.Position == position)
                {
                    return cpin;
                }
            }
            return null;
        }
    }
}

Answer

The solution to this problem was to directly select the map-element’s Custompins property to pair the correct CustomPin to the default Pins.

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);
        var customPin = (Element as CustomMap).CustomPins.FirstOrDefault(p => p.Position == pin.Position);
        if (customPin != null)
        {
            if (customPin.IconType == "corporate")
            {
                marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.corporate));
            }
            else if (customPin.IconType == "pickup")
            {
                marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.bus));
            }
        }

        return marker;
    }

Leave a Reply

Your email address will not be published. Required fields are marked *