RositsaV
RositsaV

Reputation: 101

How change xamarin.forms.maps marker with icon in Android

I want to change the current marker on xamarin.forms.maps with icon.

On my project I create CustomMap.cs class and CustomPin.cs class with this code:

using System;
using System.Collections.Generic;
using Xamarin.Forms.Maps;

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

using System;
using Xamarin.Forms.Maps;

namespace MaritsaTundzhaForecast
{
    public class CustomPin : Pin
    {
        public string Name { get; set; }
        public string Url { get; set; }
    }
}

After that I set the map on xaml page with this code:

 <Grid>
  <Label Text="Forecast Maritza-Tundzha"
         HorizontalOptions="CenterAndExpand"
         FontSize="Large"
         FontAttributes="Bold"/>
    <Grid Margin="0,30,0,10">
        <Grid.RowDefinitions>
            <RowDefinition Height="400" />
        </Grid.RowDefinitions>

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

In the same xaml page in the cs file I set marker on the map with this code:

 public MainPage()
    {
        InitializeComponent();

        CustomPin 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",
            Name = "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)));
    }

Now I read this example and I don't know how to use this code from the example in my way:

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

So I set the icon in drawable folder. What can I change from this code to use different icons and whether there is a need to change the code in another class ?

Аll day I try to replace the standard icon with another icon and fail.

Upvotes: 1

Views: 986

Answers (1)

Anand
Anand

Reputation: 1959

Like jason said there is complete sample app in the link you provided.Sample map app

You need to create a custom map renderer in your android project folder like this. Create a class named CustomMapRenderer

[assembly: ExportRenderer(typeof(CustomMap),typeof(CustomMapRenderer))]
    namespace CustomRenderer.Droid
    {
        public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
        {
            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)
                {
                    NativeMap.InfoWindowClick -= OnInfoWindowClick;
                }
    
                if (e.NewElement != null)
                {
                    var formsMap = (CustomMap)e.NewElement;
                    customPins = formsMap.CustomPins;
                }
            }
    
            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.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.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 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 customPins)
                {
                    if (pin.Position == position)
                    {
                        return pin;
                    }
                }
                return null;
            }
        }
    }

As you can see the code portion which you mentioned in this render. You can change the icon here

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

///<---- Change icon here--->
        marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
        return marker;
    }

Upvotes: 1

Related Questions