Map Renderer with custom Pin

Hi to all, I followed this guide: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/map/customized-pin/
to develop my app.
The pins work correctly but when I try to reach my device location on the map, I get a null pointer like this:

System.NullReferenceException: Object reference not set to an instance of an object
at at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/UIKit/UIApplication.cs:79
at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/UIKit/UIApplication.cs:63
at blind.iOS.Application.Main (System.String[] args) [0x00008] in /Users/alessandroa/Projects/blind/iOS/Main.cs:17

I add my location with this:

    nativeMap.ShowsUserLocation = true;
    nativeMap.SetUserTrackingMode(MKUserTrackingMode.Follow, true);

in the OnElementChanged method.
Any suggestions?

Thanks a lot!

Best Answer

Answers

  • VarunBabuSVarunBabuS INMember ✭✭✭

    hi @AlessandroAfloarei in your GetCustomPin function could you please add below condition at the top of your current code in GetCustomPin function

    if (annotation == null)
    {
    return null;
    }

    that is

    CustomPin GetCustomPin(MKPointAnnotation annotation)
    {
    if (annotation == null)
    {
    return null;
    }

            /*Your existing logic */
        }
    

    the reason to check for null is usually when you have set nativeMap.ShowsUserLocation = true; it means you are about to show user current location which is also technically speaking is an annotation of wrapper object type for which we cannot change the view hence to skip this we add this condition,

    Could you please add above conditions and let me know if you still confused please feel free to revert back I will explain in details

  • AlessandroAfloareiAlessandroAfloarei USMember ✭✭

    Hi Varun, thank you for reply.
    I following your instructions but anyway I get a null pointer when I go into the device's location with the Map.

    Here's my getCustomPin function:

        CustomPin GetCustomPin(MKPointAnnotation annotation)
        {
            if (annotation == null)
            {
                return null;
            }
            var position = new Position(annotation.Coordinate.Latitude, annotation.Coordinate.Longitude);
            foreach (var pin in customPins)
            {
                if (pin.Pin.Position == position)
                {
                    return pin;
                }
            }
            return null;
        }
    
  • AlessandroAfloareiAlessandroAfloarei USMember ✭✭

    Great, it works!!

    One last question, as soon as I press on my position I receive yet another null pointer, can I manage it?

    Thank you very much!

    Alessandro A.

  • VarunBabuSVarunBabuS INMember ✭✭✭

    Hi @AlessandroAfloarei Good could you please mark my answer as accepted answer and regarding your last question could you please try below in your code

    in function MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)

    add annotationView.CalloutOffset = new CGPoint(0, 0);

    within the condition

    if (annotationView == null)
    {
    /*Your existing logic */

                annotationView.CalloutOffset = new CGPoint(0, 0);
            }
    
  • AlessandroAfloareiAlessandroAfloarei USMember ✭✭

    Unfortunately does not go.

    Here's my GetViewForAnnotation:

    MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
        {
            MKAnnotationView annotationView = null;
    
            if (annotation is MKUserLocation)
            {
                return null;
            }
    
            var anno = annotation as MKPointAnnotation;
            var customPin = GetCustomPin(anno);
    
            if (customPin == null)
            {
                return null;
            }
    
            annotationView = mapView.DequeueReusableAnnotation(customPin.Id);
            if (annotationView == null)
            {
                annotationView = new CustomMKAnnotationView(annotation, customPin.Id);
                annotationView.Image = UIImage.FromFile("pin.png");
                annotationView.CalloutOffset = new CGPoint(0, 0);
                annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
                annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
                ((CustomMKAnnotationView)annotationView).Id = customPin.Id;
                ((CustomMKAnnotationView)annotationView).Url = customPin.Url;
            }
            annotationView.CanShowCallout = true;
    
            return annotationView;
        }
    

    Thank you very much!

    Alessandro A.

  • VarunBabuSVarunBabuS INMember ✭✭✭
    edited May 8

    hi @AlessandroAfloarei could you please replace below code

    if (annotationView == null)
    {
    annotationView = new CustomMKAnnotationView(annotation, customPin.Id);
    annotationView.Image = UIImage.FromFile("pin.png");
    annotationView.CalloutOffset = new CGPoint(0, 0);
    annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
    annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
    ((CustomMKAnnotationView)annotationView).Id = customPin.Id;
    ((CustomMKAnnotationView)annotationView).Url = customPin.Url;
    }

    with

    if (annotationView == null)
    {
    annotationView = new CustomMKAnnotationView(annotation, customPin.Id);
    annotationView.CalloutOffset = new CGPoint(0, 0);
    }

    Dont worry about customisation of annotation I shall help you further as to how customization can be done

  • AlessandroAfloareiAlessandroAfloarei USMember ✭✭

    I fixed it!
    In the method "OnDiDSelectAnnotationView" there was this:

            var customView = e.View as CustomMKAnnotationView;
            customPinView = new UIView();
    
            if (customView.Id == "Xamarin")
            {
                customPinView.Frame = new CGRect(0, 0, 200, 84);
                var image = new UIImageView(new CGRect(0, 0, 200, 84));
                image.Image = UIImage.FromFile("xamarin.png");
                customPinView.AddSubview(image);
                customPinView.Center = new CGPoint(0, -(e.View.Frame.Height + 75));
                e.View.AddSubview(customPinView);
            }
    

    I just commented the if statement ad everything works!
    Thank you so much!

    Alessandro A.

  • VarunBabuSVarunBabuS INMember ✭✭✭

    hi @AlessandroAfloarei good even i suspected the same so i asked to comment the customization related to annotation
    Fine any question regarding the Maps please feel free to comeback with you queries whether it is IOS or Android I will help you

  • AlessandroAfloareiAlessandroAfloarei USMember ✭✭

    Thank you so much!

    Alessandro A.

  • marcnegrimarcnegri CHMember ✭✭

    Hi @AlessandroAfloarei,

    Coud you please share your entire code ?
    Many thanks :)

  • BillyMartinBillyMartin USMember ✭✭

    Hi, Alessandro. I need to make my custom map pin rotate in an Xamarin Forms iOS custom renderer. Do you know how to code this, please?

  • @marcnegri said:
    Hi @AlessandroAfloarei,

    Coud you please share your entire code ?
    Many thanks :)

    Here's the entire code of method GetViewForAnnotation, sorry for the late answer.

        MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
        {
            MKAnnotationView annotationView = null;
    
            if (annotation is MKUserLocation)
            {
                return null;
            }
    
            var anno = annotation as MKPointAnnotation;
            var customPin = GetCustomPin(anno);
    
            if (customPin == null)
            {
                return null;
            }
    
            annotationView = mapView.DequeueReusableAnnotation(customPin.Id);
            if (annotationView == null)
            {
                annotationView = new CustomMKAnnotationView(annotation, customPin.Id);
                annotationView.CalloutOffset = new CGPoint(0, 0);
                annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("iconMap.png"));
                ((CustomMKAnnotationView)annotationView).Id = customPin.Id;
                ((CustomMKAnnotationView)annotationView).Url = customPin.Url;
            }
            annotationView.CanShowCallout = true;
    
            return annotationView;
        }
    

    @BillyMartin I don't understand what you mean with "pin rotate".

  • BillyMartinBillyMartin USMember ✭✭
    edited November 11

    @AlessandroAfloarei,
    By pin rotate I am saying that I have a custom map pin on a map and it is an arrow. I want it to turn (or rotate) and point in a certain direction if the user slides a slider that is below the map on the UI page.

    This is what I'm using for the Android Custom map renderer, though it is not exactly what I want since it only rotates on load and isn't linked to a slider like I really need:

    _myMarker.SetRotation((float)App.DirectionArrowRotation)

  • BillyMartinBillyMartin USMember ✭✭

    I got it using TK CustomMaps. Thanks everyone! TK CustomMaps is freaking awesome!

Sign In or Register to comment.