使用比例坐标
在AbsoluteLayout中使用比例定位可能很棘手。 有时您需要补偿考虑到大小的内部计算。 例如,您可能更喜欢指定坐标,以便X值为1表示子项的左边缘位于AbsoluteLayout的右边缘,您需要将其转换为AbsoluteLayout理解的坐标。
在下面的讨论中,一个不考虑大小的坐标 - 一个坐标,其中1表示子项位于AbsoluteLay的右边缘或底边之外? - 被称为小数坐标。本节的目标是开发将小数坐标转换为可与AbsoluteLayout一起使用的比例坐标的规则。此配置文件要求您知道子视图的大小。
假设您将名为child的视图放在名为absoluteLayout的AbsoluteLayout中,并为名为layoutBounds的子项设置布局边界矩形。让我们将此分析限制为水平坐标和大小。垂直坐标和尺寸的过程相同。
这个孩子必须先以某种方式获得宽度。子节点可以计算自己的宽度,或者可以通过LayoutBounds附加属性为与设备无关的单元分配宽度。但是我们假设设置了AbsoluteLayoutFlags.WidthProportional标志,这意味着宽度是根据布局边界的宽度字段和AbsoluteLay的宽度来计算的:
-
child.Width = layoutBounds.Width * absoluteLayout.Width
如果还设置了AbsoluteLayoutFlags.XProportional标志,那么AbsoluteLayout内部通过考虑子项的大小来计算子项相对于自身的坐标:
-
relativeChildCorrdinate.X = (absoluteLayout.Width - child.Width) * layoutBounds.X
例如,如果AbsoluteLayout的宽度为400,而子节点的宽度为100,而layoutBounds.X为0.5,则relativeChildCoordinate.X计算为150.这意味着子节点的左边缘为150 来自父级左边缘的像素。 这会导致子项在AbsoluteLayout中水平居中。
也可以计算小数子坐标:
-
fractionalChildCoordinate.X = relativeChildCoordinate.X / absoluteLayout.Width
这与比例坐标不同,因为小数子坐标为1意味着孩子的左边缘恰好位于AbsoluteLayout的右边缘之外,因此子项位于AbsoluteLayout的表面之外。 要继续该示例,小数子坐标为150除以400或0.375。 子视图的左侧位于(0.375 * 400)或距离AbsoluteLayout左边缘150个单位。
让我们重新排列公式的术语,计算要为layoutBounds.X求解的相对子坐标:
-
layoutBounds.X = relativeChildCoordinate.X / (absoluteLayout.WIdth - child.Width)
让我们将该比率的顶部和底部除以AbsoluteLayout的宽度:
-
layoutBounds.X = fractionalChildCoordinate.X / (1 - child.Width / absoluteLayout.Width)
如果你也使用比例宽度,那么分母中的那个比例是layoutBounds.Width:
-
layoutBounds.X = fractionalChildCoordinate.X / ( 1 - layoutBounds.Width)
这通常是一个非常方便的公式,因为它允许您从小数子坐标转换为比例坐标,以便在布局边界矩形中使用。
在ChessboardProportional示例中,当col等于7时,fractionalChildCoordi?nate.X为7除以列数(8)或7/8。 分母是1减1/8(正方形的比例宽度),或者再次是7/8。 比例为1。
让我们看一个公式在代码中应用于小数坐标的示例。 Propor tionalCoordinateCalc程序尝试使用粉红色AbsoluteLayout上的八个蓝色BoxView元素重现这个简单的图形:
整个数字有2:1的比例。 您可以将该图视为包含四个水平矩形和四个垂直矩形。 顶部和底部的水平蓝色矩形对具有0.1个分数单位的高度(相对于AbsoluteLayout的高度),并且从顶部和底部以及彼此之间间隔0.1个单位。 垂直的蓝色矩形看起来间隔和尺寸相似,但由于纵横比为2:1,垂直矩形的宽度为0.05个单位,并且从左侧和右侧以及彼此之间间隔0.05个单位。
AbsoluteLayout在XAML文件中定义并居中,并以粉红色着色:
-
<ContentPage xmlns=""
-
xmlns:x=""
-
x:Class="ProportionalCoordinateCalc.ProportionalCoordinateCalcPage">
-
<ContentPage.Padding>
-
<OnPlatform x:TypeArguments="Thickness"
-
iOS="5, 25, 5, 5"
-
Android="5"
-
WinPhone="5" />
-
</ContentPage.Padding>
-
<ContentView SizeChanged="OnContentViewSizeChanged">
-
<AbsoluteLayout x:Name="absoluteLayout"
-
BackgroundColor="Pink"
-
HorizontalOptions="Center"
-
VerticalOptions="Center" />
-
</ContentView>
-
</ContentPage>
代码隐藏文件定义了一个Rectangle结构数组,其中包含八个BoxView元素中每个元素的小数坐标。 在foreach循环中,程序应用上面显示的最终公式的略微变化。 而不是分母等于1减去布局的值?Bounds.Width(或layoutBounds.Height),它使用小数界限的宽度(或高度),它是相同的值。
-
public partial class ProportionalCoordinateCalcPage : ContentPage
-
{
-
public ProportionalCoordinateCalcPage()
-
{
-
InitializeComponent();
-
Rectangle[] fractionalRects =
-
{
-
new Rectangle(0.05, 0.1, 0.90, 0.1), // outer top
-
new Rectangle(0.05, 0.8, 0.90, 0.1), // outer bottom
-
new Rectangle(0.05, 0.1, 0.05, 0.8), // outer left
-
new Rectangle(0.90, 0.1, 0.05, 0.8), // outer right
-
new Rectangle(0.15, 0.3, 0.70, 0.1), // inner top
-
new Rectangle(0.15, 0.6, 0.70, 0.1), // inner bottom
-
new Rectangle(0.15, 0.3, 0.05, 0.4), // inner left
-
new Rectangle(0.80, 0.3, 0.05, 0.4), // inner right
-
};
-
foreach (Rectangle fractionalRect in fractionalRects)
-
{
-
Rectangle layoutBounds = new Rectangle
-
{
-
// Proportional coordinate calculations.
-
X = fractionalRect.X / (1 - fractionalRect.Width),
-
Y = fractionalRect.Y / (1 - fractionalRect.Height),
-
Width = fractionalRect.Width,
-
Height = fractionalRect.Height
-
};
-
absoluteLayout.Children.Add(
-
new BoxView
-
{
-
Color = Color.Blue
-
},
-
layoutBounds,
-
AbsoluteLayoutFlags.All);
-
}
-
}
-
void OnContentViewSizeChanged(object sender, EventArgs args)
-
{
-
ContentView contentView = (ContentView)sender;
-
// Figure has an aspect ratio of 2:1.
-
double height = Math.Min(contentView.Width / 2, contentView.Height);
-
absoluteLayout.WidthRequest = 2 * height;
-
absoluteLayout.HeightRequest = height;
-
}
-
}
SizeChanged处理程序只是修复了宽高比。
这是结果:
而且,当然,您可以将手机侧向转动,并在横向模式下看到更大的数字,您必须通过侧向翻书来查看:
阅读(2711) | 评论(0) | 转发(0) |