第二十六章:自定义布局(七)

简介: 垂直和水平定位简化在VerticalStack中,LayoutChildren覆盖的末尾是一个switch语句,它有助于根据子级的HorizontalOptions属性设置水平定位每个子级。 这是整个方法:public class VerticalStack : Layout<View>{ ...

垂直和水平定位简化
在VerticalStack中,LayoutChildren覆盖的末尾是一个switch语句,它有助于根据子级的HorizontalOptions属性设置水平定位每个子级。 这是整个方法:

public class VerticalStack : Layout<View>
{
    __
    protected override void LayoutChildren(double x, double y, double width, double height)
    {
        // Enumerate through all the children.
        foreach (View child in Children)
        {
            // Skip the invisible children.
            if (!child.IsVisible)
                continue;
            // Get the child's requested size.
            SizeRequest childSizeRequest = child.GetSizeRequest(width, Double.PositiveInfinity);
            // Initialize child position and size.
            double xChild = x;
            double yChild = y;
            double childWidth = childSizeRequest.Request.Width;
            double childHeight = childSizeRequest.Request.Height;
            // Adjust position and size based on HorizontalOptions.
            switch (child.HorizontalOptions.Alignment)
            {
                case LayoutAlignment.Start:
                    break;
                case LayoutAlignment.Center:
                    xChild += (width - childWidth) / 2;
                    break;
                case LayoutAlignment.End:
                    xChild += (width - childWidth);
                    break;
                case LayoutAlignment.Fill:
                    childWidth = width;
                    break;
            }
            // Layout the child.
            child.Layout(new Rectangle(xChild, yChild, childWidth, childHeight));
            // Get the next child’s vertical position.
            y += childHeight;
        }
    }
}

在编写布局时,基于其HorizontalOptions和VerticalOptions设置将子项定位在矩形内是相当频繁的。 出于这个原因,Layout 类包含一个公共静态方法,它为您执行:

public static void LayoutChildIntoBoundingRegion(VisualElement child, Rectangle region)

您可以重写LayoutChildren方法以使用此辅助方法,如下所示:

    protected override void LayoutChildren(double x, double y, double width, double height)
    {
        // Enumerate through all the children.
        foreach (View child in Children)
        {
            // Skip the invisible children.
            if (!child.IsVisible)
                continue;
            // Get the child's requested size.
            SizeRequest childSizeRequest = child.GetSizeRequest(width, Double.PositiveInfinity);
            double childHeight = childSizeRequest.Request.Height;
            // Layout the child.
            LayoutChildIntoBoundingRegion(child, new Rectangle(x, y, width, childHeight));
            // Calculate the next child vertical position.
            y += childHeight;
        }
    }

这是一个相当简化!但是,由于此调用在本章的其他布局类中使用,请记住它等同于调用子的Layout方法。
请注意,传递给LayoutChildIntoBoundingRegion的矩形包含子项可以驻留的整个区域。在这种情况下,Rectangle构造函数的width参数是传递给LayoutChildren的width参数,它是VerticalLayout本身的宽度。但Rectangle构造函数的height参数是特定子项所需的高度,可从GetSizeRequest获得。
除非子项具有Fill的默认Horizo​​ntalOptions和VerticalOptions设置,否则LayoutChildIntoBoundingRegion方法本身需要使用该Rectangle值的Width和Height属性对子项调用GetSizeRequest。这是它知道如何将子项定位在传递给方法调用的Rectangle中提供的区域内的唯一方法。
这意味着当使用LayoutChildIntoBoundingRegion方法时,VerticalLayout类可以在每个布局周期中的每个子节点上调用GetSizeRequest三次。
此外,正如VerticalLayout多次在其子节点上调用GetSizeRequest,有时使用不同的参数一样,VerticalLayout的父节点可能会使用不同的参数多次调用VerticalLayout上的GetSizeRequest,从而导致更多的OnSizeRequest调用。
调用GetSizeRequest不应该有任何副作用。调用不会导致设置任何其他属性,并且应该仅基于特定宽度和高度约束来检索信息。因此,可以比布局更自由地调用GetSizeRequest,这实际上会影响元素的大小和位置。
但如果您不需要,请不要调用GetSizeRequest。要在屏幕上显示元素,不需要调用GetSizeRequest。只需要布局。
在你自己的布局类中,最好“盲目地”处理OnSizeRequest调用,而不试图弄清楚调用的来源,或者为什么参数是它们是什么,或者用不同的参数获得多个调用意味着什么。
但是,您的布局类可以缓存OnSizeRequest调用的结果,以便您可以简化后续调用。但正确地做到这一点需要了解失效的过程。

目录
相关文章
|
6月前
|
定位技术 iOS开发
自动布局xib页面的机型匹配精典问题及解决方案
自动布局xib页面的机型匹配精典问题及解决方案
42 0
|
iOS开发
iOS动画开发之三——UIView的转场切换
iOS动画开发之三——UIView的转场切换
378 0
|
JavaScript Android开发
第二十六章:自定义布局(十)
不允许无约束的尺寸!有时您希望在屏幕上看到所有内容,可能是一系列大小统一的行和列。您可以使用带有星号定义的所有行和列定义的Grid执行类似的操作,以使它们具有相同的大小。唯一的问题是您可能还希望行数和列数基于子节点数,并针对屏幕空间的最佳使用进行了优化。
835 0
|
存储 缓存 JavaScript
第二十六章:自定义布局(九)
编码的一些规则从上面的讨论中,您可以为自己的Layout 衍生物制定几个规则:规则1:如果布局类定义了诸如间距或方向等属性,则这些属性应由可绑定属性支持。 在大多数情况下,这些可绑定属性的属性更改处理程序应调用InvalidateLayout。
2070 0
|
JavaScript Android开发
第二十六章:自定义布局(八)
失效假设您已在页面上组装了一些布局和视图,并且由于某种原因,代码隐藏文件(或者可能是触发器或行为)会更改Button的文本,或者可能只是字体大小或属性。 该更改可能会影响按钮的大小,这可能会对页面其余部分的布局更改产生连锁反应。
3421 0
|
JavaScript Android开发
第二十六章:自定义布局(十二)
更多附加的可绑定属性附加的可绑定属性也可以在XAML中设置并使用Style设置。 为了了解它是如何工作的,让我们检查一个名为CartesianLayout的类,它模仿一个二维的,四象限的笛卡尔坐标系。
540 0
|
JavaScript Android开发
第二十六章:自定义布局(六)
从Layout派生 我们现在拥有足够的知识来创建我们自己的布局类。布局中涉及的大多数公共和受保护方法都是由非泛型布局类定义的。 Layout 类派生自Layout,并将泛型类型约束为View及其派生类。
765 0
|
JavaScript Android开发
第二十六章:自定义布局(十一)
重叠的子项Layout 类可以在其子项上调用Layout方法,以便子项重叠吗?是的,但这可能会在你的脑海中提出另一个问题:什么决定孩子们的呈现顺序?哪些孩子看似坐在前台,可能部分或完全掩盖了背景中显示的其他孩子?在某些图形环境中,程序员可以访问名为Z-index的值。
643 0
|
JavaScript Android开发 iOS开发
第二十六章:自定义布局(五)
内视过程中本章到目前为止提供的大部分信息都是从包含派生自各种元素(如StackLayout,ScrollView和Label)的类的测试程序汇编而来,覆盖虚拟方法(如GetSizeRequest,OnSizeRequest,OnSizeAllocated和LayoutChildren) ,并使用System.Diagnostics命名空间中的Debug.WriteLine方法在Visual Studio或Xamarin Studio的“输出”窗口中显示信息。
762 0