使用网格排列视图
假设要生成在 7x5 网格中显示图像的页面。 可以使用多个水平和垂直 StackLayout
容器来创建此页面。 但是由于多个版式面板的内存和进程要求,可能编写代码会很繁琐,并且可能引起性能问题。 Grid
版式面板对于同时需要行和列的 UI 而言是更好的选择。 在本单元中,你将学习如何定义 Grid
以及如何在其单元格中放置视图。
什么是网格?
Grid
是由行和列构成的版式面板。 下图显示了网格的概念视图。
将视图放置在通过行和列相交而创建的单元格中。 例如,如果创建具有三列两行的 Grid
,则视图将有六个单元格。 行和列的大小可以不同,或者可以将它们设为自动调整大小以适应放入其中的子级的大小。 子视图可以占据单个单元格或跨多个单元格。 此灵活性使得 Grid
成为许多应用的根版式面板的不错选择。
如何指定网格的行和列
创建 Grid
时,可以单独定义每一行和每一列。 每行的高度和每列的宽度可完全由你控制。 每个 Grid
具有可定义网格形状的 RowDefinition
和 ColumnDefinition
对象的集合。 请使用 RowDefinition
和 ColumnDefinition
的实例填充这些集合,它们表示 UI 中的行或列。
这里有两个代码片段,显示 RowDefinition
和 ColumnDefinition
的类定义:
public sealed class RowDefinition : ...
{
...
public GridLength Height { get; set; }
}
public sealed class ColumnDefinition : ...
{
...
public GridLength Width { get; set; }
}
请注意,RowDefinition
具有一个名为 Height
的属性,ColumnDefinition
具有一个名为 Width
的属性。 请使用这些属性来设置行的高度和列的宽度,如以下部分所述。
什么是 GridLength?
Width
和 Height
属性的数据类型为 GridLength
。 此类型包含两个属性:GridUnitType
和 Value
。 下面是一个代码片段,显示一部分类型定义。
public struct GridLength
{
...
public GridUnitType GridUnitType { get; }
public double Value { get; }
}
可以将属性 GridUnitType
设为以下值之一:
Absolute
Auto
Star
现在仔细查看每个值。
绝对 GridUnitType
Absolute
指定该行或列的大小应当固定。 使用 Value
属性来表示大小。 以下示例显示如何使用 C# 将行的高度设为 100
个设备单位的固定大小。 注意 GridLength
构造函数的使用方式,该构造函数采用数字值。 此构造函数会自动将 GridUnitType
设置为 Absolute
。
var row = new RowDefinition() { Height = new GridLength(100) };
在 Extensible Application Markup Language (XAML) 中,只需提供数值。 XAML 分析程序将调用类型转换器来创建 GridLength
实例。 以下示例通过 XAML 显示相同内容:
<RowDefinition Height="100" />
自动 GridUnitType
Auto
自动调整行或列的大小,以适应子视图大小。 Grid
扫描该行或列中的所有子视图、选择最大的视图,然后将行或列的大小调整到足以适合该子视图的大小。 通过代码创建行定义时,会忽略数值。 可以使用任何值。 以下示例显示如何使用 C# 将行的高度设为自动调整大小。 请注意,我们任意选择了一个值,1
。
var row = new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) };
如果使用 XAML,则使用值 Auto
。 以下示例通过 XAML 显示相同内容。
<RowDefinition Height="Auto" />
Star GridUnitType
Star
提供按比例调整大小的功能。 在按比例调整大小时,总可用空间和每行或每列要求的比例决定了大小。 人们通常将此称为“比例缩放”而不是“按比例调整大小”。
现在来了解如何在网格中对行使用按比例调整大小。
确定可用空间:
Grid
扫描不使用比例缩放的所有行。 它将所有这些行的高度相加,然后从Grid
本身的高度中减去该总和。 通过此计算可得到可用于所有经过比例缩放的行的空间量。划分可用空间:
Grid
随后会根据各个行的Value
设置,为经比例缩放的所有行划分可用空间。 将Value
属性视为一个乘数,它为所有经过比例缩放的行确定比率。 例如,如果有两个经过比例缩放的行,都以1
作为乘数,则可用空间将在它们之间平均分配。 但如果其中一行将2
作为“值”,则它获得的空间将是另一行的两倍。
以下示例显示如何将行的高度设置为 2 Star
(C# 中):
var row = new RowDefinition() { Height = new GridLength(2, GridUnitType.Star) };
在 XAML 中,使用 *
符号来表示比例缩放。 将值和 *
合并在单个字符串中,然后类型转换器会创建 GridLength
。 下面是 XAML 中的相同示例。
<RowDefinition Height="2*" />
网格集合
使用 RowDefinition
和 ColumnDefinition
定义行和列后,可以将其添加到 Grid
。 请使用 Grid
的 RowDefinitions
和 ColumnDefinitions
集合属性。 填充这些集合的操作最常在 XAML 中完成。
此示例演示如何定义四个行并使用 RowDefinitions
属性将其添加到 Grid
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="Auto" />
<RowDefinition Height="1*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
...
</Grid>
此定义可以缩短为:
<Grid RowDefinitions="100, Auto, 1*, 2*">
...
</Grid>
用于定义列的 XAML 类似于前面的 XAML。 除非使用 ColumnDefinitions
并设置 Width
。
在运行时,此 XAML 会生成带有四个行的 Grid
。 第一行具有 100
个设备单位的高度固定。 第二行的高度与行中最高视图的高度一致。 第三和第四行使用比例缩放,这表示它们会占用剩余可用空间,并基于其各自的 Value
乘数按比例分得空间。 由于第三行是 1*
而第四行是 2*
,因此第四行的高度是第三行的两倍。
行和列的默认大小
行和列的默认大小是 1*
。 例如,请看以下 XAML。
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
...
</Grid>
此定义可以缩短为:
<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
...
</Grid>
由于未指定任何行或列的大小,因此 1*
将应用于所有行和列。 在运行时,此配置将创建一致的 Grid
,表示所有行的高度都相同,并且所有列的宽度都相同。
如何将视图添加到网格
将视图添加到 Grid
,即是将其添加到特定单元格。 单元格位于行和列相交的位置。 若要将视图放置在某单元格中,需要知道该单元格的位置。 使用行号和列号的组合来确定单元格。
行和列的编号
行和列的编号从零开始。 原始点在左上角。 下图显示四行两列的 Grid
的编号。
例如,如果要将视图添加到右下角的单元格,则可以说该视图的位置是 row 3 column 1
。
通过使用附加的属性将视图添加到网格
将视图添加到网格时,需要一种方法来指定视图的行号和列号。 一种解决方案是定义 View
基类上的 Row
和 Column
属性,以便可以直接在视图上指定位置。 此方法有用,但它不是最有效的方法。 视图不会始终在 Grid
中,因此有时不需要这些属性。 更好的方法是使用附加属性。
附加属性在某个类中进行定义,但在其他类型的对象上进行设置。
可将附加属性视为键值对的集合,该集合是视图的一部分。 将视图添加到 Grid
时,请指定行和列。 通过使用附加属性,可以添加一个键值对,它包含键 Grid.Row
和用于指定行号的值。 当 Grid
准备好放置视图时,它将检查集合以确定是否有一个名为 Grid.Row
的键。 如果有,Grid
会使用其值来放置视图。
此示例显示如何创建 Grid
以及使用附加属性添加视图:
<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
<BoxView Grid.Row="1" Grid.Column="0" Color="Navy" />
</Grid>
在此示例中,Grid.Row=1
和 Grid.Column=0
是已添加到 BoxView
的内部集合的键值对。 Grid
使用这些值来确定视图的放置位置。 这是在设备上运行应用程序时 Grid
的外观效果。
如何让视图占据多行或多列的空间
这里还有两个需要注意的附加属性:Grid.RowSpan
和 Grid.ColumnSpan
。 这些属性指定视图占据的行数或列数。 例如,请看以下 XAML。
<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
<BoxView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Color="Navy" />
</Grid>
请注意,此示例将 ColumnSpan
设置为 2
。 此视图占据从 Column 0
开始的两列。 这是在设备上运行应用程序时 Grid
的外观效果。