xamarin.iosxamarin.forms.maps

Xamarin Forms 4.1 CalloutAccessoryControlTapped is no more called for tap on annotation view


Recently, a behavior in iOS map annotation changed :

enter image description here

The event CalloutAccessoryControlTapped is no more called whe the user tap on the annotation view. For example if i tap on the red area in the image above. The only way to trigger the event is to tap on the information button to the right.

Is there a way to force CalloutAccessoryControlTapped to raise when we tap on the whole surface of the annotation ?

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

            if (Control is MKMapView nativeMap)
            {
                if (e.OldElement != null)
                {
                    nativeMap.RemoveAnnotations(nativeMap.Annotations);
                    nativeMap.GetViewForAnnotation = null;
                    nativeMap.CalloutAccessoryControlTapped -= OnCalloutAccessoryControlTapped;
                }

                if (e.NewElement != null)
                {
                    CustomMap = (CustomMap)e.NewElement;

                    nativeMap.GetViewForAnnotation = GetViewForAnnotation;
                    nativeMap.CalloutAccessoryControlTapped += OnCalloutAccessoryControlTapped;
                }
            }
        }

// event delegate
private void OnCalloutAccessoryControlTapped(object sender, MKMapViewAccessoryTappedEventArgs e)
    {
        // ...
    }

Solution

  • You can add custom a UITapGestureRecognizer to that View to achieve the effect, here are the steps:

    First, define a ges in the CustomMapRenderer :

    public class CustomMapRenderer : MapRenderer
    {
        UIView customPinView;
        List<CustomPin> customPins;
    
        UITapGestureRecognizer ges;
    
        ...
    }
    

    Then in the OnDidSelectAnnotationView, add the ges to the customView:

    void OnDidSelectAnnotationView(object sender, MKAnnotationViewEventArgs e)
    {
        var customView = e.View as CustomMKAnnotationView;
        customPinView = new UIView();
    
    
        Action action = () => {
    
            if (!string.IsNullOrWhiteSpace(((CustomMKAnnotationView)customView).Url))
            {
                UIApplication.SharedApplication.OpenUrl(new Foundation.NSUrl(((CustomMKAnnotationView)customView).Url));
            }
        };
    
        ges = new UITapGestureRecognizer(action);
        customView.AddGestureRecognizer(ges);
    
        if (customView.MarkerId == "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);
        }
    }
    

    And remove it at OnDidDeselectAnnotationView:

    void OnDidDeselectAnnotationView(object sender, MKAnnotationViewEventArgs e)
    {
    
        var customView = e.View as CustomMKAnnotationView;
        customView.RemoveGestureRecognizer(ges);
    
        if (!e.View.Selected)
        {
            customPinView.RemoveFromSuperview();
            customPinView.Dispose();
            customPinView = null;
        }
    }
    

    Refer: customized-pin