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

使用比例坐标

在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元素重现这个简单的图形:
201808312155150396

整个数字有2:1的比例。 您可以将该图视为包含四个水平矩形和四个垂直矩形。 顶部和底部的水平蓝色矩形对具有0.1个分数单位的高度(相对于AbsoluteLayout的高度),并且从顶部和底部以及彼此之间间隔0.1个单位。 垂直的蓝色矩形看起来间隔和尺寸相似,但由于纵横比为2:1,垂直矩形的宽度为0.05个单位,并且从左侧和右侧以及彼此之间间隔0.05个单位。
AbsoluteLayout在XAML文件中定义并居中,并以粉红色着色:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             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处理程序只是修复了宽高比。
这是结果:
201808312217330397
而且,当然,您可以将手机侧向转动,并在横向模式下看到更大的数字,您必须通过侧向翻书来查看:
201808312217590398

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值