Force MKAnnotationView Callout Bubble to resize when contents change

ChaseFlorellChaseFlorell CAInsider, University mod
edited March 2016 in Xamarin.iOS

Given the following snippet

public sealed class BindableMapAnnotationView : MKAnnotationView
{
    private readonly BindableMapCallout _calloutView;
    private readonly BindableMapCalloutContainer _view;

    public BindableMapAnnotationView(BindableMapAnnotation xfxAnnotation, string className, BindableMapCallout calloutView)
        : base(xfxAnnotation, className)
    {
        _calloutView = calloutView;
        _view = new BindableMapCalloutContainer(_calloutView);
        Layer.AnchorPoint = new CGPoint(0.5f, 1.0f);
        Image = xfxAnnotation.Marker;
        CanShowCallout = true;
        Selected = true;
        AutosizesSubviews = true;
        DetailCalloutAccessoryView = _view;

        _calloutView.MeasureInvalidated += CalloutViewOnMeasureInvalidated;
    }

    private void CalloutViewOnMeasureInvalidated(object sender, EventArgs eventArgs)
    {
        // how to resize the bubble around the DetailCalloutAccessoryView?
    }

    public void OnAppearing()
    {
        _calloutView.OnAppearing();
    }

    public void OnDisappearing()
    {
        _calloutView.OnDisappearing();
    }

    protected override void Dispose(bool disposing)
    {
        _calloutView.MeasureInvalidated -= CalloutViewOnMeasureInvalidated;
        base.Dispose(disposing);
    }
}

Whenever _calloutView changes it's content, it also re-draws the view and I'm able to see the new content on screen. The problem comes in the fact that the white "bubble" around the UIView doesn't resize when the content changes. I tried (to no avail) to make that method work with this.

private void CalloutViewOnMeasureInvalidated(object sender, EventArgs eventArgs)
{
    _viewContainer.SizeThatFits(new CGSize());
    _viewContainer.LayoutSubviews();
    var size = _viewContainer.Bounds;
    var rect = new CGRect(0, 0, size.Width, size.Height);
    DetailCalloutAccessoryView.Bounds = rect;
    DetailCalloutAccessoryView.SetNeedsDisplay();
    // bubble still does NOT change it's dimensions.
}


FYI, the container looks like this.


internal sealed class BindableMapCalloutContainer : UIView
{
    private readonly IVisualElementRenderer _renderer;

    public BindableMapCalloutContainer(BindableMapCallout calloutView)
    {
        _renderer = Platform.CreateRenderer(calloutView);
        Platform.SetRenderer(calloutView, _renderer);
        AddSubview(_renderer.NativeView);
    }

    // if writing another container in iOS, prefer to NOT use this unless you have to (Jason Smith)
    public override CGSize IntrinsicContentSize
    {
        get { return SizeThatFits(new CGSize()); }
    }

    public override CGSize SizeThatFits(CGSize size)
    {
        return _renderer.Element.GetSizeRequest(double.PositiveInfinity, double.PositiveInfinity).Request.ToSizeF();
    }

    public override void LayoutSubviews()
    {
        _renderer.Element.Layout(Bounds.ToRectangle());
    }
}

In the screenshots below, the Address field is initially set to Loading..., and once we reverse geo-locate the address, the size of the label changes, causing the re-draw. The view re-draws as expected but the white bubble does not.

Anyone with any thoughts?

callout 1

callout 2

callout 3

Answers

  • ChaseFlorellChaseFlorell CAInsider, University mod

    shameless bump.

  • devtest.9844devtest.9844 USMember

    Hi chase, can you provide me the code sample. I am unable to expand bubble size according to the view.

  • ChaseFlorellChaseFlorell CAInsider, University mod

    @devtest.9844 said:
    Hi chase, can you provide me the code sample. I am unable to expand bubble size according to the view.

    For iOS, I've yet to come up with a solution.

Sign In or Register to comment.