What is the proper way to add custom rendering to a Layout?

I'm trying to implement what I would call a "Panel" component. It's basically an AbsoluteLayout with a custom background. The first thing I tried was to inherit from AbsoluteLayout

public class MyPanelView : AbsoluteLayout

Then I implemented a custom renderer for iOS:

public class MyPanelRenderer : NativeRenderer
{
    protected override void OnModelSet(Xamarin.Forms.VisualElement model)
    {
        base.OnModelSet(model);

        var view = new UIView();
        view.Layer.BorderColor = UIColor.Black.CGColor;
        view.Layer.BorderWidth = 2;
        view.Layer.CornerRadius = 8;

        SetNativeControl(view);
    }
}

When I created a page with the following code

    public MainPage()
    {
        MyPanelView root = new MyPanelView();

        MyPanelView p1 = new MyPanelView();
        MyPanelView p2 = new MyPanelView();

        root.Layout.Children.Add(p1, new Rectangle(20, 60, 160, 80));
        root.Layout.Children.Add(p2, new Rectangle(20, 160, 160, 80));

        p1.Layout.Children.Add(new Label() { Text = "Label One", BackgroundColor = Color.Yellow }, new Rectangle(20, 20, 120, 40));
        p2.Layout.Children.Add(new Label() { Text = "Label Two", BackgroundColor = Color.Yellow }, new Rectangle(20, 20, 120, 40));

        Content = root;
    }

It worked as I would expect:

image

However, when I added a background color to my custom renderer

        view.Layer.BackgroundColor = UIColor.LightGray.CGColor;

It rendered very differently than I would expect:

image

At this point I figured maybe I wasn't supposed to create a custom renderer for AbsoluteLayout, so I decided to try inheriting from ContentView

public class MyPanelView : ContentView
{
    public MyPanelView()
    {
        Content = new AbsoluteLayout();
    }

    public AbsoluteLayout Layout { get { return Content as AbsoluteLayout; } }
}

I modified the MainPage properly and tried it again, and the result was even worse!

image

What is the proper way to do this?

Answers

  • BryanCassellBryanCassell USMember

    I hate to bump my own post, but this is currently a blocker for me. Surely there is a simple way to achieve this?

    Thanks,
    Bryan

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    Sorry, thank you for re-raising it, the first approach you took looks relatively sane to me, trying to figure out where it went wrong

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    BTW, the Frame class probably already does what you want

  • BryanCassellBryanCassell USMember

    Thanks for looking into this. As for frame, my example was simplified to demonstrate the problem. Our actual needs involve custom gradients/images/etc.

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    The problem is you are using the layout for the container and the children. Thats why the grey is everywhere

  • BryanCassellBryanCassell USMember

    I'm not sure what you mean by that. My example was meant to have a panel which contained two other panels, each of which contains a label. You can see this in the first screenshot. If you mean that it's not appropriate to use a Layout object as a child of another Layout, then look at my second method, where I used ContentView.

  • BryanCassellBryanCassell USMember

    Sorry to bump this again, but I'm really not sure what you meant with your response and this is still a blocker for me.

    Thanks,
    Bryan

Sign In or Register to comment.