Quintin B
Quintin B

Reputation: 5880

Xamarin forms RelativeLayout not appearing

I am following some pretty standard Xamarin forms tutorials and I am really struggling to get the RelativeLayout to work. Ultimately I want to have an ActivityIndicator overlaid on top of the mainContent:

        BindingContext = new LoginViewModel(this);
        Padding = new Thickness(20);

        Title = "Login";

        var image = new Image
        {
            Source = ImageSource.FromFile("logo.png"),
            HeightRequest = 50
        };

        var label = new Label
        {
            Text = "...",
            FontSize = 20,
            HorizontalTextAlignment = TextAlignment.Center
        };
        var errorLabel = new Label
        {
            Text = "",
            TextColor = Color.Red,
            FontSize = 20,
            HorizontalTextAlignment = TextAlignment.Center
        };

        var loginButton = new Button
        {
            Text = "Log In",
            BackgroundColor = Color.Black,
            TextColor = Color.White,
            FontSize = 20,
            HeightRequest = 50
        };

        var loginEntry = new Entry
        {
            Placeholder = "Username"
        };

        var passwordEntry = new Entry
        {
            Placeholder = "Password"
        };

        var copywrite = new Label
        {
            Text = "© 2016",
            FontSize = 15,
            HorizontalTextAlignment = TextAlignment.Center
        };

        var loadingIndicator = new ActivityIndicator
        {
            BackgroundColor = Color.Blue,
            IsVisible = true
        };

        ...

        var topLayer = new StackLayout
        {
            Spacing = 10,
            Children = { image, label, loginEntry, passwordEntry, loginButton, errorLabel },
            VerticalOptions = LayoutOptions.Start
        };

        var bottomLayer = new StackLayout
        {               
            Spacing = 10,
            Children = { copywrite },
            VerticalOptions = LayoutOptions.End
        };

        var mainContent = new StackLayout
        {
            Children =
            {
                topLayer,
                new StackLayout 
                {
                    VerticalOptions = LayoutOptions.CenterAndExpand,
                },
                bottomLayer
            },
            VerticalOptions = LayoutOptions.FillAndExpand,
            BackgroundColor = Color.Green
        };

        var r = new RelativeLayout()
        {
            BackgroundColor = Color.Pink
        };
        r.Children.Add(mainContent, 
            Constraint.RelativeToParent((parent) =>
            {
                return parent.Width;
            }),
            Constraint.RelativeToParent((parent) =>
            {
                return parent.Height;
            })
        );

        Content = r;

When I set Content = mainContent I see everything fine, but with the above code I get a white screen. I have been looking here.

When I try this:

        var overlay = new AbsoluteLayout()
        {
            BackgroundColor = Color.Pink
        };
        AbsoluteLayout.SetLayoutFlags(mainContent, AbsoluteLayoutFlags.PositionProportional);
        AbsoluteLayout.SetLayoutBounds(mainContent, new Rectangle(0f, 0f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
        AbsoluteLayout.SetLayoutFlags(loadingIndicator, AbsoluteLayoutFlags.PositionProportional);
        AbsoluteLayout.SetLayoutBounds(loadingIndicator, new Rectangle(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
        overlay.Children.Add(mainContent);
        overlay.Children.Add(loadingIndicator);

        Content = overlay;

I can see the Green and Pink views, but they may as well be stacked (as opposed to being overlaid) - but also I cannot see the Activity Indicator inside the Pink Absolute layout.

Upvotes: 1

Views: 553

Answers (1)

DavidS
DavidS

Reputation: 2944

For the RelativeLayout, the Add method you are calling is setting a constraint on X and Y, not on width and height. The order of the parameters for that variant of Add is:

  1. Child View
  2. X constraint
  3. Y constraint
  4. Width constraint
  5. Height constraint

With all constraints being optional.

To explicitly place it over the entire screen, do something like this:

r.Children.Add(mainContent, 
    Constraint.Constant(0),
    Constraint.Constant(0),
    Constraint.RelativeToParent((parent) =>
    {
        return parent.Width;
    }),
    Constraint.RelativeToParent((parent) =>
    {
        return parent.Height;
    })
);

For the AbsoluteLayout, try a slightly different set of constraints:

    AbsoluteLayout.SetLayoutFlags(mainContent, AbsoluteLayoutFlags.All);
    AbsoluteLayout.SetLayoutBounds(mainContent, new Rectangle(0f, 0f, 1f, 1f));

This explicitly specifies that mainContent is to occupy the entire AbsoluteLayout rather than relying on the actual layout size of mainContent.

Upvotes: 1

Related Questions