0

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

Chase Florell
  • 46,378
  • 57
  • 186
  • 376
  • Possible duplicate of [Force redraw of Xamarin.Forms View with custom renderer](http://stackoverflow.com/questions/25126433/force-redraw-of-xamarin-forms-view-with-custom-renderer) – Gusman Feb 29 '16 at 20:54
  • I think you're mixing things, in Xamarin Forms is not the right pattern to call to native controls from the Forms code (your code cannot be ported to Android/wphone, then why to use Forms?), you should have a custom renderer, and then on the custom renderer do the SetNeedsDisplay() – Gusman Feb 29 '16 at 20:56
  • Hello @Gusman, and thanks for taking the time to take a peek. The code above is all platform specific, and *is* within a custom renderer. The reason for this is that I've extended X.Forms Maps to have bindable callouts written in Xaml. It's quite an advanced technique, and I'm nearly there. The issue is that I'm not 100% confident in the iOS side of things (my Android works flawlessly). The callout needs to grow and shrink based on the bound content of the callout Xaml. – Chase Florell Feb 29 '16 at 21:03
  • Sorry, i read wrong your question. Did you checked the MeasureInvalidated is really being hot? – Gusman Feb 29 '16 at 21:10
  • Yes, it's definitely called when the BindingContext in the xaml is updated. As I said, it works flawlessly in Android. – Chase Florell Feb 29 '16 at 21:11
  • Could you please send the code – Aswathy K R Jun 29 '18 at 11:44

0 Answers0