Xamarin.Forms: How to center views using Relative Layout? `Width` and `Height` return -1

前端 未结 1 1245
庸人自扰
庸人自扰 2020-12-10 06:16

When trying to use the Height and Width properties of a control in Xamarin.Forms, both return -1, and it causes the Relative Layout to appear off-c

相关标签:
1条回答
  • 2020-12-10 07:01

    Why does Xamarin.Forms return -1 for Height and Width?

    Xamarin.Forms returns -1 as the default value for these properties, and it remains -1 until Xamarin.Forms creates the native control, e.g. UIButton, and adds that native control to the layout.

    In this link, you can see the Xamarin.Forms source code returning -1 as the default value: https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Core/VisualElement.cs

    Best Way to Use Relative Layouts to Constrain Views

    Option 1: Local Functions (Requires C# 7.0 or higher)

    Use a Local Function to dynamically retrieve the Width and Height properties

    var mainLayout = new RelativeLayout();
    
    //Add the Switch to the center of the screen
    mainLayout.Children.Add(mySwitch,
        Constraint.RelativeToParent(parent => parent.Width / 2 - getWidth(parent, mySwitch)/ 2),
        Constraint.RelativeToParent(parent => parent.Height / 2 - getHeight(parent, mySwitch) / 2));
    
    //Add a Label below the switch
    mainLayout.Children.Add(switchLabel,
        Constraint.RelativeToParent(parent => parent.Width / 2 - getWidth(parent, switchLabel) / 2),
        Constraint.RelativeToView(mySwitch, (parent, view) => view.Y + getHeight(parent, mySwitch) + 10));
    
    Content = mainLayout;
    
    static double getWidth(RelativeLayout parent, View view) => view?.Measure(parent.Width, parent.Height).Request.Width ?? -1;
    static double getHeight(RelativeLayout parent, View view) => view?.Measure(parent.Width, parent.Height).Request.Height ?? -1;
    

    Option 2: Func<RelativeLayout, double>

    Use a Func to dynamically retrieve the Width and Height properties

    var mainLayout = new RelativeLayout();
    
    Func<RelativeLayout, double> getSwitchWidth = (parent) => mySwitch.Measure(parent.Width, parent.Height).Request.Width;
    Func<RelativeLayout, double> getSwitchHeight = (parent) => mySwitch.Measure(parent.Width, parent.Height).Request.Height;
    Func<RelativeLayout, double> getLabelWidth = (parent) => switchLabel.Measure(parent.Width, parent.Height).Request.Width;
    Func<RelativeLayout, double> getLabelHeight = (parent) => switchLabel.Measure(parent.Width, parent.Height).Request.Height;
    
    //Add the Switch to the center of the screen
    mainLayout.Children.Add(mySwitch,
        Constraint.RelativeToParent(parent => parent.Width / 2 - getSwitchWidth(parent)/ 2),
        Constraint.RelativeToParent(parent => parent.Height / 2 - getSwitchHeight(parent) / 2));
    
    //Add a Label below the switch
    mainLayout.Children.Add(switchLabel,
        Constraint.RelativeToParent(parent => parent.Width / 2 - getLabelWidth(parent) / 2),
        Constraint.RelativeToView(mySwitch, (parent, view) => view.Y + getSwitchHeight(parent) + 10));
    
    Content = mainLayout;
    

    Thanks to @BrewMate for teaching me this trick!

    0 讨论(0)
提交回复
热议问题