2
votes

I’m trying to create a “generic” renderer for iOS and I have trouble figuring out the dimensions of the renderer.

The class of the renderer in the PCL is very simple and the only “peculiar” is that inherits from a View since I want to have it as a generic renderer

public class ExampleView : View { }

In the XAML, it is also very typical

<renderers:ExampleView />

The definition of the renderer in the iOS project is the following

public class ExampleRenderer : ViewRenderer<ExampleView, UIView>
{
    protected override void OnElementChanged(ElementChangedEventArgs<ExampleView> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            SetNativeControl(new UIView(new CGRect(0, 0, 0, 300)));
        }
    }
}

The interesting part here is that the class inherits from ViewRenderer<ExampleView, UIView>

It seems that although I specify that the width of the render to be 0, the actual renderer takes the entire width of the page.

In fact whatever value I put as width, will be disregarded, and the renderer will occupy the entire page.

This is not bad, it is unintentional and this is what bother me. (or Am I doing something wrong?)

So the question here is how can find in my custom render, the width that occupies?

1

1 Answers

3
votes

It is not the renderer, but the native control that is taking up the space. The renderer is doing it's job i.e. keep the native control in sync with forms control - which includes layout parse requests.

To control the size constraints I would recommend using the properties WidthRequest or HeightRequest on forms Element to do that. It will automatically trickle down to the native Control.Frame through the renderer.

EDIT-1

If you want to update your native controls (or subviews) based on current bounds you can use OnElementPropertyChanged to track the changes. There can many reasons that can cause a size-update - like device-orientation change, parent layout, first layout pass etc.

public class ExampleRenderer : ViewRenderer<ExampleView, UIView>
{
    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (e.PropertyName == VisualElement.WidthProperty.PropertyName ||
            e.PropertyName == VisualElement.HeightProperty.PropertyName)
        {
            if(Element != null && Element.Bounds.Height > 0 && Element.Bounds.Width > 0)
            {
                //update size on native control's subviews
                // or use SetNeedsDisplay() to re-draw
                //Note: force update to Control's size is not recommended (as it is recommended it be same as forms element)
                //Instead add a subview that you can update for size here
            }   
        }
    }