Xamarin 的窗体布局选项,尤其是填充和展开方式,有何不同?

在 Xamarin。表单每个 View都有两个属性 HorizontalOptionsVerticalOptions。两者都属于 LayoutOptions类型,可以具有以下值之一:

  • LayoutOptions.Start
  • LayoutOptions.Center
  • LayoutOptions.End
  • LayoutOptions.Fill
  • LayoutOptions.StartAndExpand
  • LayoutOptions.CenterAndExpand
  • LayoutOptions.EndAndExpand
  • LayoutOptions.FillAndExpand

显然,它控制着视图在父视图上的对齐方式。但是每个选项的行为到底是怎样的呢?Fill和后缀 Expand的区别是什么?

55802 次浏览

长话短说

StartCenterEndFill定义视图的 在其空间内排列

如果可用,Expand定义 它是否占据了更多的空间

理论

LayoutOptions结构控制着两种截然不同的行为:

  1. 对齐: < em > 视图在父视图中如何对齐?

    • Start: 对于垂直对齐,视图被移动到顶部。对于水平对齐,这通常是左侧。(但是请注意,在设置了从右到左语言设置的设备上,这是相反的,即右对齐。)
    • 视图是居中的。
    • End: 通常视图是底部对齐或右对齐的。(在从右到左的语言中,当然是左对齐。)
    • Fill: 这种对齐方式略有不同。视图将横跨父视图的整个大小。

    但是,如果父级不比它的子级大,则不会注意到这些对齐之间的任何差异。对于具有额外可用空间的父视图,仅对齐事项。

  2. 扩展: < em > 如果可用的话,元素会占据更多的空间吗?

    • 后缀 Expand: 如果父视图大于其所有子视图的合并大小,即有额外的空间可用,那么该空间将在具有该后缀的子视图中按比例分配。这些孩子会“占据”他们的空间,但不一定“填补”它。我们将在下面的例子中看到这种行为。
    • 没有后缀: 没有 Expand后缀的孩子不会得到额外的空间,即使有更多的空间可用。

    同样,如果父视图不大于其子视图,则扩展后缀也不会产生任何差异。

例子

让我们看一下下面的示例,看看所有八种布局选项之间的区别。

该应用程序包含一个深灰色的 StackLayout与八个嵌套的白色按钮,其中每一个标签与其垂直布局选项。当单击其中一个按钮时,它将其垂直布局选项分配给堆栈布局。这样,我们可以很容易地测试视图与父视图的交互,两者都有不同的布局选项。

(最后几行代码添加了额外的黄色框。稍后我们将回过头来讨论这个问题。)

public static class App
{
static readonly StackLayout stackLayout = new StackLayout {
BackgroundColor = Color.Gray,
VerticalOptions = LayoutOptions.Start,
Spacing = 2,
Padding = 2,
};


public static Page GetMainPage()
{
AddButton("Start", LayoutOptions.Start);
AddButton("Center", LayoutOptions.Center);
AddButton("End", LayoutOptions.End);
AddButton("Fill", LayoutOptions.Fill);
AddButton("StartAndExpand", LayoutOptions.StartAndExpand);
AddButton("CenterAndExpand", LayoutOptions.CenterAndExpand);
AddButton("EndAndExpand", LayoutOptions.EndAndExpand);
AddButton("FillAndExpand", LayoutOptions.FillAndExpand);


return new NavigationPage(new ContentPage {
Content = stackLayout,
});
}


static void AddButton(string text, LayoutOptions verticalOptions)
{
stackLayout.Children.Add(new Button {
Text = text,
BackgroundColor = Color.White,
VerticalOptions = verticalOptions,
HeightRequest = 20,
Command = new Command(() => {
stackLayout.VerticalOptions = verticalOptions;
(stackLayout.ParentView as Page).Title = "StackLayout: " + text;
}),
});
stackLayout.Children.Add(new BoxView {
HeightRequest = 1,
Color = Color.Yellow,
});
}
}

下面的截图显示了点击这八个按钮的结果,我们观察到以下几点:

  • 只要父 stackLayout是紧密的(不 Fill的页面) ,每个 Button的垂直布局选项是可以忽略不计的。
  • 垂直布局选项只有在 stackLayout更大(例如通过 Fill对齐)和单个按钮有 Expand后缀的情况下才起作用。
  • 所有带 Expand后缀的按钮之间的额外空间是按比例分配的。为了更清楚地看到这一点,我们在每两个相邻的按钮之间添加了黄色的水平线。
  • 空间大于请求高度的按钮不一定“填充”它。在这种情况下,实际行为由它们的对齐方式控制。例如,它们要么在空间的顶部、中心或按钮上对齐,要么完全填满。
  • 所有按钮跨越整个布局的宽度,因为我们只修改 VerticalOptions

Screenshots

在这里您可以找到相应的高分辨率屏幕截图。

当前版本的 Xamarin 有一点缺陷。形式; 也许已经存在一段时间了。

CenterAndExpand通常不会扩展,绕过它可能会让人感到困惑。

例如,如果你有一个 StackLayout设置为 CenterAndExpand,然后你把一个标签内,也设置为 CenterAndExpand,你会期望一个标签是完全宽度的 StackLayout。没有。它不会膨胀。您必须将 StackLayout设置为“ FillAndExpand”以使嵌套的 Label 对象展开到 StackLayout的全宽,然后告诉 Label 使用 HorizontalTextAlignment="Center"以文本为中心,而不是将其本身作为对象。根据我的经验,如果您真的想确保它扩展到适合,那么您需要将父代和嵌套的子代都设置为 FillAndExpand

        <StackLayout HorizontalOptions="FillAndExpand"
Orientation="Vertical"
WidthRequest="300">
<Label BackgroundColor="{StaticResource TileAlerts}"
HorizontalOptions="FillAndExpand"
Style="{StaticResource LabelStyleReversedLrg}"
HorizontalTextAlignment="Center"
Text="Alerts" />

Falko 给出了一个很好的解释,但是我想用另外一个视觉效果来补充这一点,以及这些标签在 xaml 中是如何工作的,这也是我大多数时候更喜欢使用的。我做了一个测试显示结果的简单项目。以下是主页的 Xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Alignments.MainPage"
BackgroundColor="White">




<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="LightGray" Padding="1" Margin="30">
<Label Text="Vert: EndAndExpand, Horz: EndAndExpand" VerticalOptions="EndAndExpand" HorizontalOptions="EndAndExpand" BackgroundColor="White"/>
</StackLayout>




</ContentPage>

正如您所看到的,这是一个非常简单的 StackLayout,其中包含一个 Label。对于下面的每个图片,我保持 StackLayout 不变,我只是更改了 Entry 的水平和垂直选项,并更改了文本以显示选定的选项,这样您就可以看到 Entry 如何移动和调整大小。

Start vs StartAndExpand 下面是开始使用的代码:

<Label Text="Vert: Start, Horz: Start" VerticalOptions="Start" HorizontalOptions="Start" BackgroundColor="White"/>

以及 StartAndExpand 所使用的代码:

<Label Text="Vert: StartAndExpand, Horz: StartAndExpand" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" BackgroundColor="White"/>

正如您可以看到的,除了 StartAndExpand 选项中使用了更多的文本之外,在视觉上没有任何区别。这是在我的三星 A30物理设备上测试的。这些可能在不同的设备上显示不同,但是我认为这里所有的图片都表明在 Xamarin 有一些 bug。至于其余的,我将只展示屏幕截图,我认为他们是不言而喻的。

End vs EndAndExpand

Center vs CenterAndExpand

Fill vs FillAndExpand

我还建议看看 Microsoft 文档以获得一些额外的细节。值得注意的是“扩展仅由 StackLayout 使用”。