2

I am use the Xamarin iOS MKMapView, and i am trying to have separate images for each pin, but when I override the GetViewForAnnotation method, it makes all the pins the same image, is there a way to make every pin a different image.

class MapDelegate : MKMapViewDelegate
        {
            static string annotationId = "CustomAnnotation";
            UIImageView venueView;
            UIImage venueImage;

            public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
            {
                MKAnnotationView annotationView = null;

                if (annotation is MKUserLocation)
                    return null; 

                if (annotation is CustomAnnotation) {

                    // show conference annotation
                    annotationView = mapView.DequeueReusableAnnotation (annotationId);

                    if (annotationView == null)
                        annotationView = new MKAnnotationView (annotation, annotationId);

                    UIImage image = ImageSource.FromFile("image.png");
                } 

                return annotationView;
            }

            public override MKOverlayView GetViewForOverlay (MKMapView mapView, NSObject overlay)
            {
                // return a view for the polygon
                MKPolygon polygon = overlay as MKPolygon;
                MKPolygonView polygonView = new MKPolygonView (polygon);
                polygonView.FillColor = UIColor.Blue;
                polygonView.StrokeColor = UIColor.Red;
                return polygonView;
            }
        }

And the constructor:

map.MapType = MKMapType.Standard;
            map.ShowsUserLocation = true;
            map.ZoomEnabled = true;
            map.ScrollEnabled = true;

            map.DidUpdateUserLocation += (sender, ex) => {
                if (map.UserLocation != null) {
                    CLLocationCoordinate2D userLocation = map.UserLocation.Coordinate;
                    MKCoordinateSpan range = new MKCoordinateSpan(MilesToLatitudeDegrees(5), MilesToLongitudeDegrees(5, userLocation.Latitude));
                    MapDelegate mapDelegate = new MapDelegate();
                    map.Delegate = mapDelegate;

                    /*ADDING MULTIPLE ANNOTATIONS HERE*/
                        }
                    }
                }
            };

I want to set each annotation to a different custom pin image, can someone help THANK YOU.

user3841879
  • 659
  • 3
  • 12
  • 21
  • In GetViewForAnnotation, the code shown never sets annotationView.image. Anyway, see http://stackoverflow.com/questions/25184753/different-custom-image-for-each-pin/25186602#25186602 for an example (will need to convert to C#). –  Aug 23 '14 at 11:35
  • Also, instead of creating a span by manually converting miles to degrees, it might be better to use the built-in [MKCoordinateRegion.FromDistance](http://iosapi.xamarin.com/index.aspx?link=M%3AMonoTouch.MapKit.MKCoordinateRegion.FromDistance) method and let the SDK do the conversion to degrees for you. You specify meters instead of degrees so you just need to convert miles to meters. –  Aug 23 '14 at 11:37
  • How do i convert this line to C#: pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotationView"]; pinView.canShowCallout = YES; pinView.calloutOffset = CGPointMake(0, 32); and this line: pinView.image = [UIImage imageNamed:ca.pinName]; – user3841879 Aug 23 '14 at 16:26
  • [This question](http://stackoverflow.com/questions/17531119/ios-pin-annotation-shows-initially-then-custom-images-are-used-after) has some sample code in C# for your reference. –  Aug 23 '14 at 20:50

1 Answers1

0

This is possible by using Converter, for example you can specify concrete icon based on concrete pin property value.

private MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
    {
        MKAnnotationView annotationView = null;
        var formsMap = Element as MapWithPins;
        if (_customPins.Count == 0 || formsMap.PinsSource.Count != _customPins.Count)
        {
            //if (formsMap.PinsSource.Count != 0)
            _customPins = formsMap.PinsSource;
        }
        if (annotation is MKUserLocation)
            return null;
        if (!(annotation is MKPointAnnotation))
        {
            DrawMyLocationMarker(annotation, out annotationView);
        }
        else
        {
            var customPin = GetCustomPin(annotation as MKPointAnnotation);
            if (customPin == null)
                throw new Exception("Custom Pin not found");

            annotationView = mapView.DequeueReusableAnnotation(customPin.Guid.ToString());
            if (annotationView == null)
            {
                DrawMarkerForAnnotationView(annotation, out annotationView, customPin);
                if (customPin.Order > 0)
                    DrawNumber(customPin, annotationView);
            }
            else
                annotationView.Annotation = annotation;
        }
        return annotationView;
    }

As you can see I draw different icons based on properties. If Order property of my pin is more than 0, then I draw Order number on it. Otherwise in DrawMarkerFirAnnotationView I had Converter which returns proper icon based on properties.

private static void DrawMarkerForAnnotationView(IMKAnnotation annotation, out MKAnnotationView annotationView,
        PinViewModel customPin)
    {
        annotationView = new MKAnnotationView(annotation, customPin.Guid.ToString());
        var contractor= new Contractor { ContractorType = customPin.ContractorType, CompetitorPriceLastDate = customPin.CompetitorPriceLastDate, HasActivity = customPin.HasActivity };
        annotationView.Image =
            UIImage.FromFile(
                new ContractorToIconConverter().Convert(contractor, typeof(ContractorType), null, null).ToString());
    }

I'm sure that you noticed, that icons are based on ContractorType property

public class BusRelToIconConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is Contractor)
        {
            var contractor= (Contractor)value;
            if (contractor.HasActivity)
            {
                if (busRel.IsVisitedToday())
                {
                    return "marker-yellow-visited.png";
                }
                else
                {
                    return "marker-yellow.png";
                }
            }
            else if (contractor.ContractorType == CustStatus.Competitor)
            {
                if (contractor.IsVisitedToday())
                {
                    return "marker-red-visited.png";
                }
                else
                {
                    return "marker-red.png";
                }
            }
            else
            {
                if (contractor.IsVisitedToday())
                {
                    return "marker-blue-visited.png";
                }
                else
                {
                    return "marker-blue.png";
                }
            }
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Good luck!

mashet
  • 836
  • 1
  • 10
  • 17