指定视图大小

已完成

设计在各种设备上一致的用户界面非常困难,因为设备具有不同大小和不同的像素密度。 试想不同的可用设备:手机、平板电脑、桌面设备等。 如何创建在每个设备上看起来相似的用户界面?

.NET MAUI 提供有助于生成一致的用户界面的版式面板。 布局面板负责调整其子级视图的大小和位置。 在本单元中,你将了解布局系统如何在 .NET MAUI 中运作。 具体而言,我们将了解默认情况下视图的大小调整方式,以及如何在运行时请求视图的特定大小和位置。

什么是版式面板?

版式面板是一种 .NET MAUI 容器,包含子视图的集合并决定子视图的大小和位置。 应用大小更改时,版式面板会自动进行重新计算;例如,用户旋转设备时。

注意

术语“视图”或“子视图”是指放置在版式面板上的控件。 视图可以是标签、按钮、输入字段或 .NET MAUI 支持的任何其他类型的视觉元素。

.NET MAUI 具有可供选择的多个版式面板。 每个面板以不同的方式管理其子视图。 下图显示了一些最常见选项的概念性概述。

Illustration showing representative StackLayout, AbsoluteLayout, FlexLayout, and Grid designs.

  • StackLayout:将其子视图排列在单个行或列中。 除了 StackLayout 之外,在不需要更改方向时,还有经优化的新 VerticalStackLayoutHorizontalStackLayout
  • AbsoluteLayout:使用 x 和 y 坐标排列其子视图。
  • Grid:在从行和列的交集创建的单元格中排列其子视图。
  • FlexLayout:像 StackLayout 一样排列其子视图,只不过在这些子视图不适合单个行或列时可以包装它们。

注意

还有第五种类型的版式面板,称为 RelativeLayout,它使你能够指定如何相对地排列子视图。 应使用 FlexLayout 控件而不是 RelativeLayout,因为它的性能更好。 RelativeLayout 包含在 .NET MAUI 中,以便向后兼容较旧的 Xamarin 应用。

生成 .NET MAUI 页面的典型过程是创建版式面板,然后向其添加子视图。 将视图添加到布局时,操作者可影响其大小和位置。 但是,面板根据其内部布局算法具有最终设置权限。

在考虑如何请求视图的特定大小之前,让我们先看看默认情况下布局系统如何调整视图的大小。

视图的默认大小

如果未指定视图的大小,它将自动增加到足以容纳其内容的大小。 例如,请考虑此 XAML:

<Label
    Text="Hello"
    BackgroundColor="Silver"
    VerticalOptions="Center"
    HorizontalOptions="Center" 
    FontSize="40"/>

本示例定义用于在银色背景上显示单词 Hello 的标签。 由于未指定大小,标签会自动调整大小以围绕单词 Hello。 下图显示了 Android 设备上呈现的标签:

Screenshot showing a label rendered on an Android device that displays the word Hello in the center with a silver background.

注意

可以设置标签的背景色,以确定标签在运行时的大小。 在生成 UI 时,请记得这是一种不错的调试方法。

指定视图大小

生成 UI 时,通常希望能控制视图的大小。 例如,假设要生成登录页面,并希望登录按钮正好是屏幕宽度的一半。 如果使用的是默认的视图大小调整方式,则按钮大小仅为文本“登录”的大小。 该大小不够大,因此你需要自行指定大小。

View 基类定义影响视图大小的两个属性:WidthRequestHeightRequest。 通过 WidthRequest 可指定宽度,通过 HeightRequest 可指定高度。 两个属性的类型都是 double

以下示例显示如何通过 XAML 指定标签的宽度和高度:

<Label
    Text="Hello"
    BackgroundColor="Silver"
    VerticalOptions="Center"
    HorizontalOptions="Center"
    WidthRequest="100"
    HeightRequest="300"
    FontSize="40"/>

结果类似以下形式:

Screenshot showing a label rendered on an Android device that displays the word Hello in the center with a silver background. The label is sized explicitly

注意

尽管标签的文本不在标签的中心,但标签仍然居中。

值得注意的一点是这些属性的名称。 两个属性都包含“请求”一词。 该词表示版式面板可能不会在运行时应用它们。 版式面板在大小调整计算期间读取这些值,并尝试满足这些请求(如果可以)。 如果没有足够的空间,版式面板可以忽略这些值。

尺寸单位

设置 WidthRequestHeightRequest 时,使用类似于 100 的文本值。 在 .NET MAUI 级别,这些值没有单位。 它们不是点或像素。 它们只是 double 类型的值。 .NET MAUI 在运行时将这些值传递到基础操作系统。 操作系统提供确定数字含义所需的上下文:

  • 在 iOS 上,这些值称为“点”
  • 在 Android 上,它们是“与密度无关的像素”

所呈现的视图大小

因为是由版式面板确定视图的大小,所以无法使用 WidthRequestHeightRequest 在运行时指示实际大小。 例如,假设为标签将 WidthRequest 设置为 100,但是面板没有足够的控件来满足该请求。 面板会为标签提供宽度 80。 此时,如果你查看 WidthRequest 属性值的话,你会看到 100,虽然呈现的值为 80

若要解决此问题,View 基类需定义其他两个名为 WidthHeight 的属性。 这些属性的类型是 double,表示所呈现的视图宽度和高度。 无论何时检索视图的大小,都使用 WidthHeight 属性。

指定视图的位置

此外,需要设置视图位置。 例如,回想一下,在登录页面示例中,你希望将登录按钮的大小调整为屏幕宽度的一半。 由于登录按钮的宽度不到屏幕的整个宽度,因此有其他剩余空间,可将其进行移动。 可以将其放置在屏幕左边、右边或中心。

View 基类具有用于设置视图位置的两个属性:VerticalOptionsHorizontalOptions。 这些设置会影响视图在版式面板为其分配的矩形内的位置。 可以将视图指定与矩形的四条边之一对齐。 或者,可以让视图占据整个矩形。

指定 VerticalOptionsHorizontalOptions 的值比设置大小更难,因为它们的类型是 LayoutOptions

什么是 LayoutOptions 类型?

LayoutOptions 为 C# 类型,包含两个布局首选项:AlignmentExpands。 这两个属性与位置相关,但它们彼此不相关。 类型的定义如下所示:

public struct LayoutOptions
{
    public LayoutAlignment Alignment { get; set; }
    public bool Expands { get; set; }
    ...
}

接下来,我们更详细地了解 Alignment,因为它是最常用且最直观的布局选项。

什么是 LayoutAlignment 枚举?

LayoutAlignment 是包含四个值的枚举:StartCenterEndFill。 可以使用这些值来控制子视图在版式面板为其提供的矩形内的位置。 以下面的代码和 Android 屏幕截图为例:

<StackLayout>
    <Label Text="Start" HorizontalOptions="Start" BackgroundColor="Silver" FontSize="40" />
    <Label Text="Center" HorizontalOptions="Center" BackgroundColor="Silver"  FontSize="40" />
    <Label Text="End" HorizontalOptions="End" BackgroundColor="Silver"  FontSize="40"/>
    <Label Text="Fill" HorizontalOptions="Fill" BackgroundColor="Silver"  FontSize="40"/>
</StackLayout>

Screenshot showing four labels rendered on iOS with different HorizontalOptions: Start to the left side, Center centered, End to the right side, and Fill spanning the full screen.

该示例使用的是垂直 StackLayout,因此每个子视图都有一行。 HorizontalOptions 确定视图在其行内的位置。

什么是 Expands?

LayoutOptions 结构的第二个属性是 ExpandsExpands 属性是 bool,在 Xamarin.forms 中使 StackLayout 中的视图能够请求额外的空间(如果有)。 此属性现已过时,.NET MAUI 中不再使用。 稍后,我们将了解如何在 Grid 布局的单元中实现相同类型的扩展。

知识检查

1.

LayoutPanel 的作用是什么?