AbsoluteLayout

Browse sample.浏览示例

.NET MAUI AbsoluteLayout.

.NET Multi-platform App UI (.NET MAUI) AbsoluteLayout 用于使用显式值调整子级的位置和大小。 该位置按与设备无关的单位,由相对于 AbsoluteLayout 左上角的子级的左上角指定。 AbsoluteLayout 还实现了按比例定位和调整大小的功能。 此外,与其他一些布局类不同,AbsoluteLayout 能够调整子级的位置,因而子级间可以重叠。

AbsoluteLayout 应视为特殊用途的布局,仅在你可以设置子级的大小或元素的大小不影响其他子级的位置时使用。

AbsoluteLayout 类定义以下属性:

  • LayoutBounds,类型为 Rect,它是一个附加属性,表示子级的位置和大小。 此属性的默认值为 (0,0,AutoSize,AutoSize)。
  • LayoutFlags,类型为 AbsoluteLayoutFlags,是一个附加属性,指示用于调整子级位置和大小的布局边界的属性是否按比例解读。 此属性的默认值为 AbsoluteLayoutFlags.None

所有这些属性都由 BindableProperty 对象提供支持,这意味着这些属性可以作为数据绑定的目标并设置样式。 有关附加属性的详细信息,请参阅 .NET MAUI 附加属性

调整子级的位置和大小

通过使用绝对值或比例值设置每个子级的 AbsoluteLayout.LayoutBounds 附加属性来定义 AbsoluteLayout 中子级的位置和大小。 当位置应缩放时,子级的绝对值和比例值可以混用,但大小应保持固定,反之亦然。 有关绝对值的信息,请参阅调整绝对位置和大小。 有关比例值的信息,请参阅按比例调整位置和大小

无论使用绝对值还是比例值,都可以使用两种格式设置 AbsoluteLayout.LayoutBounds 附加属性:

  • x, y。 使用此格式时,xy 值指示子级的左上角相对于其父级的位置。 子级不受约束,自行调整大小。
  • x, y, width, height。 使用此格式时,xy 值指示子级的左上角相对于其父级的位置,而 widthheight 值指示子级的大小。

要指定子级在水平和/或垂直方式自行调整大小,请将 width 和/或 height 值设置为 AbsoluteLayout.AutoSize 属性。 但是,过度使用此属性可能会损害应用程序性能,因为会导致布局引擎执行额外的布局计算。

重要

HorizontalOptionsVerticalOptions 属性对 AbsoluteLayout 的子级不起作用。

调整绝对位置和大小

默认情况下,AbsoluteLayout 会按与设备无关的单位,使用绝对值调整子级的位置和大小,从而显式定义子级应在布局中放置的位置。 为此,要将子级添加到 AbsoluteLayout 并将每个子级的 AbsoluteLayout.LayoutBounds 附加属性设置为绝对位置和/或大小值。

警告

使用绝对值调整子级的位置和大小可能会出问题,因为不同设备的屏幕大小和分辨率也不同。 因此,一台设备上的屏幕中心坐标在其他设备上可能会出现偏移。

以下 XAML 显示了使用绝对值调整子级位置的 AbsoluteLayout

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="AbsoluteLayoutDemos.Views.XAML.StylishHeaderDemoPage"
             Title="Stylish header demo">
    <AbsoluteLayout Margin="20">
        <BoxView Color="Silver"
                 AbsoluteLayout.LayoutBounds="0, 10, 200, 5" />
        <BoxView Color="Silver"
                 AbsoluteLayout.LayoutBounds="0, 20, 200, 5" />
        <BoxView Color="Silver"
                 AbsoluteLayout.LayoutBounds="10, 0, 5, 65" />
        <BoxView Color="Silver"
                 AbsoluteLayout.LayoutBounds="20, 0, 5, 65" />
        <Label Text="Stylish Header"
               FontSize="24"
               AbsoluteLayout.LayoutBounds="30, 25" />
    </AbsoluteLayout>
</ContentPage>

在此示例中,使用 AbsoluteLayout.LayoutBounds 附加属性中指定的前两个绝对值来定义每个 BoxView 对象的位置。 每个 BoxView 的大小是使用第三个和第四个值定义的。 Label 对象的位置是使用 AbsoluteLayout.LayoutBounds 附加属性中指定的两个绝对值定义的。 没有为 Label 指定大小值,因此其大小不受约束并可自行调整。 在所有情况下,绝对值表示与设备无关的单位。

以下屏幕截图显示了生成的布局:

Children placed in an AbsoluteLayout using absolute values.

等效 C# 代码如下所示:

public class StylishHeaderDemoPage : ContentPage
{
    public StylishHeaderDemoPage()
    {
        AbsoluteLayout absoluteLayout = new AbsoluteLayout
        {
            Margin = new Thickness(20)
        };

        absoluteLayout.Add(new BoxView
        {
            Color = Colors.Silver
        }, new Rect(0, 10, 200, 5));
        absoluteLayout.Add(new BoxView
        {
            Color = Colors.Silver
        }, new Rect(0, 20, 200, 5));
        absoluteLayout.Add(new BoxView
        {
            Color = Colors.Silver
        }, new Rect(10, 0, 5, 65));
        absoluteLayout.Add(new BoxView
        {
            Color = Colors.Silver
        }, new Rect(20, 0, 5, 65));

        absoluteLayout.Add(new Label
        {
            Text = "Stylish Header",
            FontSize = 24
        }, new Point(30,25));                     

        Title = "Stylish header demo";
        Content = absoluteLayout;
    }
}

在此示例中,每个 BoxView 的位置和大小都是使用 Rect 对象定义的。 使用 Point 对象定义 Label 的位置。 C# 示例使用以下 Add 扩展方法将子级添加到 AbsoluteLayout

using Microsoft.Maui.Layouts;

namespace Microsoft.Maui.Controls
{
    public static class AbsoluteLayoutExtensions
    {
        public static void Add(this AbsoluteLayout absoluteLayout, IView view, Rect bounds, AbsoluteLayoutFlags flags = AbsoluteLayoutFlags.None)
        {
            if (view == null)
                throw new ArgumentNullException(nameof(view));
            if (bounds.IsEmpty)
                throw new ArgumentNullException(nameof(bounds));

            absoluteLayout.Add(view);
            absoluteLayout.SetLayoutBounds(view, bounds);
            absoluteLayout.SetLayoutFlags(view, flags);
        }

        public static void Add(this AbsoluteLayout absoluteLayout, IView view, Point position)
        {
            if (view == null)
                throw new ArgumentNullException(nameof(view));
            if (position.IsEmpty)
                throw new ArgumentNullException(nameof(position));

            absoluteLayout.Add(view);
            absoluteLayout.SetLayoutBounds(view, new Rect(position.X, position.Y, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
        }
    }
}

在 C# 中,在将 AbsoluteLayout 的子级添加到布局中之后,还可以使用 AbsoluteLayout.SetLayoutBounds 方法来设置其位置和大小。 此方法的第一个参数是子级,第二个参数是 Rect 对象。

注意

使用绝对值的 AbsoluteLayout 可以调整子级的位置和大小,这样可能导致其不适合布局的边界。

按比例调整位置和大小

AbsoluteLayout 可以使用比例值调整子级的位置和大小。 通过将子级添加到 AbsoluteLayout 并将每个子级上的 AbsoluteLayout.LayoutBounds 附加属性设置为介于 0-1 之间的比例位置和/或大小值达成此目的。 通过在每个子级上设置 AbsoluteLayout.LayoutFlags 附加属性,按比例调整位置和大小值。

类型为 AbsoluteLayoutFlagsAbsoluteLayout.LayoutFlags 附加属性允许设置标志,该标志指示子级的布局边界位置和大小值与 AbsoluteLayout 的大小成正比。 布局子级时,AbsoluteLayout 会根据设备大小相应缩放位置和大小值。

AbsoluteLayoutFlags 枚举定义下列成员:

  • None,指示值将被解释为绝对值。 这是附加属性 AbsoluteLayout.LayoutFlags 的默认值。
  • XProportional,指示 x 值将被解释为比例值,同时将所有其他值视为绝对值。
  • YProportional,指示 y 值将被解释为比例值,同时将所有其他值视为绝对值。
  • WidthProportional,指示 width 值将被解释为比例值,同时将所有其他值视为绝对值。
  • HeightProportional,指示 height 值将被解释为比例值,同时将所有其他值视为绝对值。
  • PositionProportional,指示 xy 值将被解释为比例值,而大小值被解释为绝对值。
  • SizeProportional,指示 widthheight 值将被解释为比例值,而位置值被解释为绝对值。
  • All,指示所有值都将解释为比例值。

提示

AbsoluteLayoutFlags 枚举是 Flags 枚举,这意味着可以组合枚举成员。 在 XAML 中使用逗号分隔的列表,以及在 C# 中使用按位 OR 运算符均可达成此目的。

例如,如果使用 SizeProportional 标志并将子级的宽度设置为 0.25,将高度设置为 0.1,则子级的宽度将是 AbsoluteLayout 宽度的四分之一和高度的十分之一。 PositionProportional 标志与此类似。 位置 (0,0) 将子级置于左上角,位置 (1,1) 将子级置于右下角,而位置 (0.5,0.5) 将子级置于 AbsoluteLayout 中心。

以下 XAML 显示其子级使用比例值进行定位的 AbsoluteLayout

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="AbsoluteLayoutDemos.Views.XAML.ProportionalDemoPage"
             Title="Proportional demo">
    <AbsoluteLayout>
        <BoxView Color="Blue"
                 AbsoluteLayout.LayoutBounds="0.5,0,100,25"
                 AbsoluteLayout.LayoutFlags="PositionProportional" />
        <BoxView Color="Green"
                 AbsoluteLayout.LayoutBounds="0,0.5,25,100"
                 AbsoluteLayout.LayoutFlags="PositionProportional" />
        <BoxView Color="Red"
                 AbsoluteLayout.LayoutBounds="1,0.5,25,100"
                 AbsoluteLayout.LayoutFlags="PositionProportional" />
        <BoxView Color="Black"
                 AbsoluteLayout.LayoutBounds="0.5,1,100,25"
                 AbsoluteLayout.LayoutFlags="PositionProportional" />
        <Label Text="Centered text"
               AbsoluteLayout.LayoutBounds="0.5,0.5,110,25"
               AbsoluteLayout.LayoutFlags="PositionProportional" />
    </AbsoluteLayout>
</ContentPage>

在此示例中,每个子级都使用比例值定位,但使用绝对值调整大小。 可以通过将每个子级的 AbsoluteLayout.LayoutFlags 附加属性设置为 PositionProportional 达成此目的。 在 AbsoluteLayout.LayoutBounds 附加属性中针对每个子级指定的前两个值使用比例值来定义位置。 每个子级的大小采用第三个和第四个绝对值以与设备无关的单位定义。

以下屏幕截图显示了生成的布局:

Children placed in an AbsoluteLayout using proportional position values.

等效 C# 代码如下所示:

public class ProportionalDemoPage : ContentPage
{
    public ProportionalDemoPage()
    {
        BoxView blue = new BoxView { Color = Colors.Blue };
        AbsoluteLayout.SetLayoutBounds(blue, new Rect(0.5, 0, 100, 25));
        AbsoluteLayout.SetLayoutFlags(blue, AbsoluteLayoutFlags.PositionProportional);

        BoxView green = new BoxView { Color = Colors.Green };
        AbsoluteLayout.SetLayoutBounds(green, new Rect(0, 0.5, 25, 100));
        AbsoluteLayout.SetLayoutFlags(green, AbsoluteLayoutFlags.PositionProportional);

        BoxView red = new BoxView { Color = Colors.Red };
        AbsoluteLayout.SetLayoutBounds(red, new Rect(1, 0.5, 25, 100));
        AbsoluteLayout.SetLayoutFlags(red, AbsoluteLayoutFlags.PositionProportional);

        BoxView black = new BoxView { Color = Colors.Black };
        AbsoluteLayout.SetLayoutBounds(black, new Rect(0.5, 1, 100, 25));
        AbsoluteLayout.SetLayoutFlags(black, AbsoluteLayoutFlags.PositionProportional);

        Label label = new Label { Text = "Centered text" };
        AbsoluteLayout.SetLayoutBounds(label, new Rect(0.5, 0.5, 110, 25));
        AbsoluteLayout.SetLayoutFlags(label, AbsoluteLayoutFlags.PositionProportional);

        Title = "Proportional demo";
        Content = new AbsoluteLayout
        {
            Children =  { blue, green, red, black, label }
        };
    }
}

在此示例中,使用 AbsoluteLayout.SetLayoutBounds 方法设置每个子级的位置和大小。 该方法的第一个参数是子级,第二个参数是 Rect 对象。 每个子级的位置均使用比例值设置,而每个子级的大小则采用绝对值以与设备无关的单位设置。

注意

使用比例值的 AbsoluteLayout 可以通过使用 0-1 之外的值来调整子级的位置和大小,这会导致其不适合布局的边界。