第十四章:绝对布局(四)

2720阅读 0评论2018-08-31 renxiao2003
分类:Android平台

使用比例坐标

在AbsoluteLayout中使用比例定位可能很棘手。 有时您需要补偿考虑到大小的内部计算。 例如,您可能更喜欢指定坐标,以便X值为1表示子项的左边缘位于AbsoluteLayout的右边缘,您需要将其转换为AbsoluteLayout理解的坐标。
在下面的讨论中,一个不考虑大小的坐标 - 一个坐标,其中1表示子项位于AbsoluteLay的右边缘或底边之外? - 被称为小数坐标。本节的目标是开发将小数坐标转换为可与AbsoluteLayout一起使用的比例坐标的规则。此配置文件要求您知道子视图的大小。
假设您将名为child的视图放在名为absoluteLayout的AbsoluteLayout中,并为名为layoutBounds的子项设置布局边界矩形。让我们将此分析限制为水平坐标和大小。垂直坐标和尺寸的过程相同。
这个孩子必须先以某种方式获得宽度。子节点可以计算自己的宽度,或者可以通过LayoutBounds附加属性为与设备无关的单元分配宽度。但是我们假设设置了AbsoluteLayoutFlags.WidthProportional标志,这意味着宽度是根据布局边界的宽度字段和AbsoluteLay的宽度来计算的:

点击(此处)折叠或打开

  1. child.Width = layoutBounds.Width * absoluteLayout.Width
如果还设置了AbsoluteLayoutFlags.XProportional标志,那么AbsoluteLayout内部通过考虑子项的大小来计算子项相对于自身的坐标:

点击(此处)折叠或打开

  1. relativeChildCorrdinate.X = (absoluteLayout.Width - child.Width) * layoutBounds.X
例如,如果AbsoluteLayout的宽度为400,而子节点的宽度为100,而layoutBounds.X为0.5,则relativeChildCoordinate.X计算为150.这意味着子节点的左边缘为150 来自父级左边缘的像素。 这会导致子项在AbsoluteLayout中水平居中。
也可以计算小数子坐标:

点击(此处)折叠或打开

  1. fractionalChildCoordinate.X = relativeChildCoordinate.X / absoluteLayout.Width
这与比例坐标不同,因为小数子坐标为1意味着孩子的左边缘恰好位于AbsoluteLayout的右边缘之外,因此子项位于AbsoluteLayout的表面之外。 要继续该示例,小数子坐标为150除以400或0.375。 子视图的左侧位于(0.375 * 400)或距离AbsoluteLayout左边缘150个单位。
让我们重新排列公式的术语,计算要为layoutBounds.X求解的相对子坐标:

点击(此处)折叠或打开

  1. layoutBounds.X = relativeChildCoordinate.X / (absoluteLayout.WIdth - child.Width)
让我们将该比率的顶部和底部除以AbsoluteLayout的宽度:

点击(此处)折叠或打开

  1. layoutBounds.X = fractionalChildCoordinate.X / (1 - child.Width / absoluteLayout.Width)
如果你也使用比例宽度,那么分母中的那个比例是layoutBounds.Width:

点击(此处)折叠或打开

  1. 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文件中定义并居中,并以粉红色着色:

点击(此处)折叠或打开

  1. <ContentPage xmlns=""
  2.              xmlns:x=""
  3.              x:Class="ProportionalCoordinateCalc.ProportionalCoordinateCalcPage">
  4.     <ContentPage.Padding>
  5.         <OnPlatform x:TypeArguments="Thickness"
  6.                     iOS="5, 25, 5, 5"
  7.                     Android="5"
  8.                     WinPhone="5" />
  9.     </ContentPage.Padding>
  10.     <ContentView SizeChanged="OnContentViewSizeChanged">
  11.         <AbsoluteLayout x:Name="absoluteLayout"
  12.                         BackgroundColor="Pink"
  13.                         HorizontalOptions="Center"
  14.                         VerticalOptions="Center" />
  15.     </ContentView>
  16. </ContentPage>
代码隐藏文件定义了一个Rectangle结构数组,其中包含八个BoxView元素中每个元素的小数坐标。 在foreach循环中,程序应用上面显示的最终公式的略微变化。 而不是分母等于1减去布局的值?Bounds.Width(或layoutBounds.Height),它使用小数界限的宽度(或高度),它是相同的值。

点击(此处)折叠或打开

  1. public partial class ProportionalCoordinateCalcPage : ContentPage
  2. {
  3.     public ProportionalCoordinateCalcPage()
  4.     {
  5.         InitializeComponent();
  6.         Rectangle[] fractionalRects =
  7.         {
  8.             new Rectangle(0.05, 0.1, 0.90, 0.1), // outer top
  9.             new Rectangle(0.05, 0.8, 0.90, 0.1), // outer bottom
  10.             new Rectangle(0.05, 0.1, 0.05, 0.8), // outer left
  11.             new Rectangle(0.90, 0.1, 0.05, 0.8), // outer right
  12.             new Rectangle(0.15, 0.3, 0.70, 0.1), // inner top
  13.             new Rectangle(0.15, 0.6, 0.70, 0.1), // inner bottom
  14.             new Rectangle(0.15, 0.3, 0.05, 0.4), // inner left
  15.             new Rectangle(0.80, 0.3, 0.05, 0.4), // inner right
  16.         };
  17.         foreach (Rectangle fractionalRect in fractionalRects)
  18.         {
  19.             Rectangle layoutBounds = new Rectangle
  20.             {
  21.                 // Proportional coordinate calculations.
  22.                 X = fractionalRect.X / (1 - fractionalRect.Width),
  23.                 Y = fractionalRect.Y / (1 - fractionalRect.Height),
  24.                 Width = fractionalRect.Width,
  25.                 Height = fractionalRect.Height
  26.             };
  27.             absoluteLayout.Children.Add(
  28.                 new BoxView
  29.                 {
  30.                     Color = Color.Blue
  31.                 },
  32.                 layoutBounds,
  33.                 AbsoluteLayoutFlags.All);
  34.         }
  35.     }
  36.     void OnContentViewSizeChanged(object sender, EventArgs args)
  37.     {
  38.         ContentView contentView = (ContentView)sender;
  39.         // Figure has an aspect ratio of 2:1.
  40.         double height = Math.Min(contentView.Width / 2, contentView.Height);
  41.         absoluteLayout.WidthRequest = 2 * height;
  42.         absoluteLayout.HeightRequest = height;
  43.     }
  44. }
SizeChanged处理程序只是修复了宽高比。
这是结果:

而且,当然,您可以将手机侧向转动,并在横向模式下看到更大的数字,您必须通过侧向翻书来查看:

上一篇:第十四章:绝对布局(三)
下一篇:第十四章:绝对布局(五)