:::tip
本章涉及知识点:

  • RelativePanel 的相对方位
  • RelativePanel 的适用场景
    :::

什么是相对方位

在日常生活中,当我们想描述某个物体的位置时,我们一般都会用相对位置来描述。比如“小张就在班主任的后面”,而不是“小张在北纬42°,东经112°”。

相对位置的描述总是会先确定一个参照物,然后其它物体的位置信息都是相对参照物而言的。而这一点,正是 RelativePanel 的布局核心。

RelativePanel 如何布局

上节课,我们讲述了StackPanel ,那时候我们说StackPanel内的子元素像排队,秩序井然,排序严格。但在实际布局中,我们并不总是需要这种严格的布局排版。

就如上节课举的例子,当一个容器内只有两个元素,我想让它们一左一右地排列,StackPanel 就不能实现,但 RelativePanel 却可以。因为在 RelativePanel 中,并不会对子元素的位置进行限制,其中的子元素理论上可以出现在容器内的任何位置。

RelativePanel 又名相对布局,在RelativePanel 中,确定子元素位置的除了常规的Margin之外,便是一系列用以描述相对位置的属性,概览如下:

属性名说明
Above在某元素上方
Below在某元素下方
LeftOf在某元素左边
RightOf在某元素右边
AlignTopWith本元素的上边缘与某元素的上边缘对齐
AlignBottomWith本元素的下边缘与某元素的下边缘对齐
AlignLeftWith本元素的左边缘与某元素的左边缘对齐
AlignRightWith本元素的右边缘与某元素的右边缘对齐
AlignVerticalCenterWith本元素与某元素的垂直居中对齐
AlignHorizontalCenterWith本元素与某元素水平居中对齐
AlignTopWithPanel是否与容器上边缘对齐
AlignBottomWithPanel是否与容器下边缘对齐
AlignLeftWithPanel是否与容器左边缘对齐
AlignRightWithPanel是否与容器右边缘对齐
AlignVerticalCenterWithPanel是否在容器中垂直居中对齐
AlignHorizontalCenterWithPanel是否在容器中水平居中对齐

通过上面的表格你就可以发现,RelativePanel 为子元素提供了大量的附加属性来帮助确定其相对位置 (其中的垂直居中前端开发者看了想必会很感动) 。而正如本文开头所述,相对位置建立在至少有一个参照物的基础上。

我们可以说“Logo在导航按钮的右边”,那么这个时候我们就要在Logo所代表的元素标签内使用附加属性RelativePanel.RightOf="导航按钮",这样你也发现了,为了能获取导航按钮元素,那么就必须事先给导航按钮命名,也就是给导航按钮的Name属性赋值。

话不多说,让我们来实现一个简单的顶部导航栏布局吧。

顶部导航栏布局

在本例中,我们需要四个元素,分别是菜单按钮、标题文本、后退按钮和前进按钮。最终布局如下图所示:

uwp_relativepanel_01.png

首先我们为顶部导航栏腾出空间来,即将整个页面分作导航栏+内容区。这里我们就可以利用Grid进行操作:

1
2
3
4
5
6
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>

第二行不管,我们在第一行新建一个 RelativePanel。

1
2
3
4
5
6
7
8
9
10
11
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<RelativePanel Height="50" Background="DarkGray">

</RelativePanel>

</Grid>

在此之后,我们先把所用到的元素写进去

1
2
3
4
5
6
7
8
9
10
11
12
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<RelativePanel Height="50" Background="DarkGray">
<Button Width="50" Height="50" Content="&#xE700;" FontFamily="{StaticResource SymbolThemeFontFamily}" Name="MenuButton" />
<TextBlock Name="HeaderTextBlock" Text="首页" FontSize="20" FontWeight="Bold" />
<Button Name="NextButton" FontFamily="{StaticResource SymbolThemeFontFamily}" Content="&#xE72A;" Height="50" Width="50" />
<Button Name="PreviousButton" FontFamily="{StaticResource SymbolThemeFontFamily}" Content="&#xE72B;" Height="50" Width="50" />
</RelativePanel>
</Grid>

到了这里,我们就完成了一半的工作了。接下来的一半则是本章内容的核心,即给元素确定位置:

  1. 菜单按钮在页面最左边,故使用与容器相对齐的AlignLeftWithPanel属性。
  2. 标题文本在菜单按钮的右边,并与其有一定的间隔,同时它又是垂直居中的,所以要搭配使用RightOfAlignVertialCenterWithPanelMargin
  3. 前进和后退按钮在页面的右侧,而前进按钮在最右侧,故优先写前进按钮,之后后退按钮便以前进按钮为参照进行定位,涉及属性AlignRightWithPanelLeftOf

故完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<RelativePanel Height="50" Background="DarkGray">
<Button Width="50" Height="50" Content="&#xE700;" FontFamily="{StaticResource SymbolThemeFontFamily}" Name="MenuButton" RelativePanel.AlignLeftWithPanel="True"/>
<TextBlock Text="首页" FontSize="20" FontWeight="Bold" RelativePanel.RightOf="MenuButton" RelativePanel.AlignVerticalCenterWithPanel="True" Margin="15,0,0,0"/>
<Button Name="NextButton" Content="&#xE72A;" FontFamily="{StaticResource SymbolThemeFontFamily}" Height="50" Width="50" RelativePanel.AlignRightWithPanel="True"/>
<Button Name="PreviousButton" Content="&#xE72B;" FontFamily="{StaticResource SymbolThemeFontFamily}" Height="50" Width="50" RelativePanel.LeftOf="NextButton"/>
</RelativePanel>
</Grid>

RelativePanel 的适用场景

如你所见,RelativePanel 的布局更加自由,同时又能通过相对位置保留一丝“秩序”这个秩序是相对完全自由的绝对定位容器Canvas而言的

RelativePanel 常用于卡片式布局之中。比如一个视频卡片,卡片的高度可能随着内容会有变化,但始终要求视频发布日期(或标签、点赞数等)在卡片底部。类似这种场景就可以考虑 RelativePanel 。

其它的还有很多,比如对居中对齐有要求的布局,都可以使用RelativePanel。

RelativePanel虽有其局限,但同时也是非常强大的布局工具,尤其是在强调自适应的UWP应用中,更是有着得天独厚的优势,它能够确保在软件窗口大小改变时,布局仍能维持大体稳定。

小结

本章对相对布局容器RelativePanel有了一个大概的介绍。RelativePanel 会给子元素提供很多的附加属性用以描述其相对位置,这个相对位置的参照可以是容器,也可以是容器内的其它子元素。

而落实到生产环境,Grid、StackPanel、RelativePanel,这些布局控件的特性都有一定重叠,换句话说,总会有替代方案,只不过有些容器控件会更容易达到目标罢了,了解这些布局容器的特性,按照自己的需要灵活选取合适的容器才是你真正要做的。

除了介绍的Grid、StackPanel和RelativePanel之外,还有如Canvas、VariableSizedWrapGrid等布局控件(在Windows Community Toolkit中还有更多),这些控件我不再细说,如果你感兴趣,可以自行了解。

延伸阅读

轉載來自 https://blog.richasy.cn/