在Xamarin.Forms中,布局的概念包含了可以在屏幕上组合各种视图的所有方式。 这是类层次结构,显示从Layout派生的所有类:
-
System.Object
-
BindableObject
-
Element
-
VisualElement
-
View
-
Layout
-
ContentView
-
Frame
-
ScrollView
-
Layout<T>
-
AbsoluteLayout
-
Grid
-
RelativeLayout
-
StackLayout
你已经看过ContentView,Frame和ScrollView(所有这些都有一个你可以设置为一个子节点的Content属性),你已经看到了StackLayout,它继承了Layout
中的Children属性并显示了它的子节点垂直或水平堆叠。
Grid和RelativeLayout实现了一些复杂的布局模型,并将在以后的章节中进行探讨。 AbsoluteLayout是本章的主题。
起初,AbsoluteLayout类似乎实现了一个相当原始的布局模型
-
当程序员需要单独调整大小并定位屏幕上的每个元素时,这个模型可以追溯到不太好的图形用户界面。然而,你会发现AbsoluteLayout还采用了比例定位和尺寸调整功能,有助于将这种古老的布局模型带入现代。
使用AbsoluteLayout,到目前为止您学习的许多关于布局的规则不再适用:当View是ContentPage或StackLayout的子项时,如此重要的HorizontalOptions和VerticalOptions属性在View是子项时绝对没有效果一个AbsoluteLayout。程序必须为AbsoluteLayout的每个子项分配与设备无关的坐标中的特定位置。还可以为孩子分配特定大小或允许孩子自己调整大小。
您可以在代码或XAML中使用AbsoluteLayout。
无论哪种方式,您都会遇到一个您尚未看到的功能,这是BindableObject和BindableProperty提供的支持的另一部分。
此新功能是附加的可绑定属性。
这是一种特殊类型的可绑定属性,由一个类(在本例中为AbsoluteLayout)定义,但在其他对象(AbsoluteLayout的子节点)上设置。
代码中的AbsoluteLayout
您可以像使用StackLayout一样将子视图添加到AbsoluteLayout的Children集合中:
-
absoluteLayout.Children.Add(child);
但是,您还有其他选择。 AbsoluteLayout类将其Children属性重新定义为AbsoluteLayout.IAbsoluteList
类型,其中包括两个额外的Add方法,允许您指定子项相对于AbsoluteLayout左上角的位置。 您可以选择指定孩子的大小。
要指定位置和大小,请使用Rectangle值。 Rectangle是一个结构,您可以使用接受Point和Size值的构造函数创建Rectangle值:
-
Point point = new Point(x, y);
-
Size size = new Size(width, height);
-
Rectangle rect = new Rectangle(point, size);
或者,您可以将x,y,width和height参数直接传递给Rectangle构造函数:
-
Rectangle rect = new Rectangle(x, y, width, height);
然后,您可以使用另一种Add方法将视图添加到AbsoluteLayout的Children集合中:
-
absoluteLayout.Children.Add(child, rect);
x和y值指示子视图的左上角相对于设备无关坐标中AbsoluteLayout父项的左上角的位置。 如果您希望孩子自己调整大小,则只能使用没有Size值的Point值:
-
absoluteLayout.Children.Add(child, point);
这是一个名为AbsoluteDemo的程序中的一个小演示:
-
public class AbsoluteDemoPage : ContentPage
-
{
-
public AbsoluteDemoPage()
-
{
-
AbsoluteLayout absoluteLayout = new AbsoluteLayout
-
{
-
Padding = new Thickness(50)
-
};
-
absoluteLayout.Children.Add(
-
new BoxView
-
{
-
Color = Color.Accent
-
},
-
new Rectangle(0, 10, 200, 5));
-
absoluteLayout.Children.Add(
-
new BoxView
-
{
-
Color = Color.Accent
-
},
-
new Rectangle(0, 20, 200, 5));
-
absoluteLayout.Children.Add(
-
new BoxView
-
{
-
Color = Color.Accent
-
},
-
new Rectangle(10, 0, 5, 65));
-
absoluteLayout.Children.Add(
-
new BoxView
-
{
-
Color = Color.Accent
-
},
-
new Rectangle(20, 0, 5, 65));
-
absoluteLayout.Children.Add(
-
new Label
-
{
-
Text = "Stylish Header",
-
FontSize = 24
-
},
-
new Point(30, 25));
-
absoluteLayout.Children.Add(
-
new Label
-
{
-
FormattedText = new FormattedString
-
{
-
Spans =
-
{
-
new Span
-
{
-
Text = "Although the "
-
},
-
new Span
-
{
-
Text = "AbsoluteLayout",
-
FontAttributes = FontAttributes.Italic
-
},
-
new Span
-
{
-
Text = " is usually employed for purposes other " +
-
"than the display of text using "
-
},
-
new Span
-
{
-
Text = "Label",
-
FontAttributes = FontAttributes.Italic
-
},
-
new Span
-
{
-
Text = ", obviously it can be used in that way. " +
-
"The text continues to wrap nicely " +
-
"within the bounds of the container " +
-
"and any padding that might be applied."
-
}
-
}
-
}
-
},
-
new Point(0, 80));
-
this.Content = absoluteLayout;
-
}
-
}
四个BoxView元素在顶部形成一个重叠的十字形图案以引出标题,然后是一段文字。 程序定位和调整所有BoxView元素,而它只是定位两个Label视图,因为它们自己调整大小:
需要进行一些试验和错误才能使四个BoxView元素的大小和标题文本的大小大致相同。但请注意BoxView元素重叠:AbsoluteLayout允许您以非常自由的方式重叠视图,这对于StackLayout来说根本不可能(或者不使用变换,这将在后面的章节中介绍)。
AbsoluteLayout的一大缺点是你需要自己设定定位坐标或在运行时计算它们。任何未明确调整大小的内容(例如两个Label视图)都会在页面布局时计算自身的大小。但是那个尺寸直到那时才可用。如果您想在第二个Label之后添加另一个段落,您会使用什么坐标?
实际上,您可以通过在AbsoluteLayout中放置StackLayout(或ScrollView内的StackLayout)然后将Label视图放入其中来定位多段文本。布局可以嵌套。
您可以推测,使用AbsoluteLayout比使用StackLayout更困难。通常,让Xamarin.Forms和其他布局类为您处理大部分布局复杂性要容易得多。但对于一些特殊用途,AbsoluteLayout是理想的选择。
与所有可视元素一样,AbsoluteLayout默认将其HorizontalOptions和VerticalOptions属性设置为Fill,这意味着AbsoluteLayout填充其容器。使用HorizontalOptions和VerticalOptions的其他设置,AbsoluteLayout将自身的大小调整为其内容的大小,但也有一些例外:尝试在AbsoluteDemo中给出AbsoluteLayout
编程BackgroundColor,以便您可以准确地看到它在屏幕上占据的空间。它通常填充整个页面,但是如果设置HorizontalOptions和VerticalOptions属性
对于中心的AbsoluteLayout,您将看到AbsoluteLayout为其自身计算的大小包括内容和填充,但只包含文本段落的一行。
确定AbsoluteLayout中视觉元素的大小可能很棘手。下面的ChessboardFixed程序演示了一种简单的方法。程序名称后缀为Fixed,因为棋盘中所有方块的位置和大小都是在构造函数中设置的。构造函数无法预测屏幕的大小,因此它可以任意设置每个方块的大小为35个单位,如类顶部的squareSize常量所示。此值应足够小,以使棋盘适合Xamarin.Forms支持的任何设备的屏幕。
请注意,AbsoluteLayout是居中的,因此它的大小可以容纳其所有子节点。电路板本身有浅黄色,浅黄色,然后在每个其他方形位置显示32个深绿色BoxView元素:
-
public class ChessboardFixedPage : ContentPage
-
{
-
public ChessboardFixedPage()
-
{
-
const double squareSize = 35;
-
AbsoluteLayout absoluteLayout = new AbsoluteLayout
-
{
-
BackgroundColor = Color.FromRgb(240, 220, 130),
-
HorizontalOptions = LayoutOptions.Center,
-
VerticalOptions = LayoutOptions.Center
-
};
-
for (int row = 0; row < 8; row++)
-
{
-
for (int col = 0; col < 8; col++)
-
{
-
// Skip every other square.
-
if (((row ^ col) & 1) == 0)
-
continue;
-
BoxView boxView = new BoxView
-
{
-
Color = Color.FromRgb(0, 64, 0)
-
};
-
Rectangle rect = new Rectangle(col * squareSize,
-
row * squareSize,
-
squareSize, squareSize);
-
absoluteLayout.Children.Add(boxView, rect);
-
}
-
}
-
this.Content = absoluteLayout;
-
}
-
}
对row和col变量的异或计算仅在row或col变量为奇数但两者都不是奇数时才会创建BoxView。 这是结果:
阅读(2113) | 评论(0) | 转发(0) |