ios 约束(二)

来源:互联网 发布:阿里云服务器代理商 编辑:程序博客网 时间:2024/06/07 03:20

1、约束系统的运作规律

    可以认为约束系统所用的数学算是非常严格,实际上它们只是个参考。iOS会找到对符合约束的一种布局方案,有的时候,这种方案不止一套。下面给出约束系统的一些基本特征:

    1、约束规则描述的是关系,而不一定是视图在某个方向上的属性。未必非要在知道右边界的情况下才能算出左边界。

    2、每条约束规则都有其优先级。优先级的取值范围是从0到1000.Auto Layout系统用优先级来排列各条约束的顺序。他总是先设法满足优先级较高的约束规则,然后再去满足优先级较低的规则。优先级为99的规则总是排在优先级为100的规则后面。在排布视图位置的时候,系统会遍历开发者所添加的全部影响力。假如刚才说的那两条约束规则互相冲突,那么系统会考虑优先级为100 的那条规则,而放弃优先级为99的那条。

    优先级最高的约束规则是必须要满足,它的类型是UILayoutPriorityRequired,其值为1000,而这种类型也是系统默认的约束类型。优先级为1000的约束必须完全满足才行,比方说,我们可以表达出”此按钮必须是这种尺寸“等意图。假如某条约束规则的优先级不是1000,那么它在整个布局系统里的影响力就变弱了。

    但即便是必须满足的约束,也有可能在发生冲突的情况下遭到覆盖。如果我们没有权衡好各条规则之间的关系,那么很有可能令本来应该是100 * 100 的视图变成102 * 107.


    3、除了优先级这一因素之外,各条约束规则之间并没有其他自然的顺序。系统会同时考虑优先级相同的一系列约束。如果想令某条约束占先,那么可以提升其优先级。

    4、有些约束规则只需大致满足即可。我们可以用一些可选的约束规则来试着优化一下布局效果。比方说,”2号视图的定边应该和1号视图的底边处在同一位置“。约束系统会试着令两个视图靠近,并尽量缩小其距离。假如有其他约束规则使得这两个视图无法紧贴,那么系统会尽可能的令它们靠拢,以缩小这两个属性之间的差距。

    5、约束规则之间可以有循环。所涉及的控件只要都满足规则就行了,并不需要明确每个视图具体对应于规则中的哪个物件。不要跟交叉引用较劲。这套声明式的系统可以接受循环引用,所以开发者无需担心无限循环问题。

    6、可以用动画来表现约束规则的变化过程。从一套约束规则切换到另一套的时候,可以用UIView的动画功能来表现这个过程。在动画块中,我们可以改变约束规则之后调用layoutIfNeeded,这样的话,视图就会以动画效果来展现由上一套约束规则切换到新规则的过程。

    7、在约束规则里可以引用同一体系里的其他视图。对于某个视图来说,可以令其中一个子视图的中心点与另外一个完全不同的视图的中心点相对齐,只要两者之间有公共的祖先视图即可。比方说,我们创建了一种复杂的文本输入视图,其中还嵌套有UIImageView控件,那么现在可以令它最右侧那个按钮的right属性与按钮下方UIImageView控件的right属性相对齐。

    8、约束规则不应该跨越边界系统。在指定对齐方式的时候,不要跨越UIScrollView、UICollectionView及UITableView的边界。如果某种视图有它自己的边界系统,那么就不要从一个边界系统跳到另一个完全不同的边界系统里面去。虽说这么做可能不会使程序崩溃,但毕竟不是个好办法,而且Auto Layout对这种做法的支持度也不好。

    9、Auto Layout与transform之间可能配合的不够好。同时使用transform及Auto Layout 时要多加小心,尤其在涉及旋转的情况下更是如此。

    10、Auto Layout不能和运动效果一起工作。由UIMotionEffect实例所产生的视觉变化只会影响视图的CALayer,而不会干扰底层的布局。

    11、约束规则在运行期可能会出错。如果系统无法解析开发者所设定的约束规则,或是规则之间有冲突,那么运行期系统就会丢弃一些规则,以便尽量吧视图排布出来。这种做法很不优雅,而且经常会产生于程序需求不符的布局。Auto Layout会把详尽的信息发送到Xcode控制台,告诉开发者哪里出了错,我们可以根据这些错误报告来修正约束规则,使各条规则之间和谐一致。

    12、格式错误的约束可能会阻断应用程序的执行。规则之间若有了冲突,则只会产生错误信息,而应用程序还是可以运行的,但是,如果规则的格式写错了,那么执行了某些调用之后,程序就会因为未处理的异常而崩溃。

    13、每条约束规则必须至少引用一个视图。如果创建了一条没有引用任何视图的约束规则,那么Xcode在编译代码时不会产生警告,但程序却会在运行的时候抛出异常。

    14、避免无效的属性搭配。把某个视图的左边界和另一个视图的高度相匹配是不合法的。无效的属性组合会令程序在运行的时候抛出异常。尤其不应该吧尺寸有关的属性和与边界有关的属性混起来用。一般来说,我们都能够把有问题的属性组合检查出来,因为那些属性搭配在一起是没有意义的。

2、约束规则与框架属性

    Auto Layout的强大之处基本上在于:它排布UI的同时,还可以处理内容多变的视图。UIView有两个属性,分别是固有内容的尺寸以及对齐矩形,该矩形的范围可以超越传统的框架,以便使Auto Layout系统能够适当的处理视图之间的关系。

    1、固有内容的尺寸

    在Auto Layout系统中,视图的内容与视图的约束规则一样,都对布局起着重要的作用。内容是通过每个视图的intrinsicContentSize属性表达出来的。该方法描述了在既不挤压也不裁切的前提下完全容纳视图内所需的最小空间,其含义可以根据每个视图所要表示内容而推断出来。

    例如,对于UIImageView来说,这就相当于其中的图像所具备的尺寸。图像如果比较大,那么intrinsicContentSize也会大一些。而对于标签控件来说,则取决于字体和文本量。标签控件的intrinsicContentSize会随着文本长短与所选字体而变化。

    有了intrinsicContentSize之后,Auto Layout系统就可以把视图的框架属性也其内容较好的匹配起来。我们通常需要在每个轴上设置两种属性才能避免约束规则过少或排版方式有歧义等情况。为视图指定了intrinsicContentSize之后,就相当于已经有了其中一个属性。现在我们可以把某个基于文本的控件或UIImageView控件放在上级视图的中心,这样的排版方案只有一种,所以不会产生歧义。把intrinsicContentSize与location结合起来,就可以完整的确定视图的排布方式了。实际上,Auto Layout系统在排版时会把intrinsicContentSize  解析成一条约束规则。

    改变视图的内容之后,我们可以调用invalidateIntrinsicContentSize方法,以此告知Auto Layout系统下次排版时应重新计算intrinsicContentSize。

    Compression Resistance与Content Hugging

    Auto Layout系统在判定intrinsicContentSize的大小时会受到两个属性的影响。正如其名称所示,Compression Resistance(抗挤压性)表示视图保护其内容不受压缩的能力。抗挤压性越高的视图,越不容易收缩。他要竭力避免内容遭到裁剪。而Content Hugging(内容凝聚度)则表示一种优先级,他指明视图是否不愿意在其核心内容之外添加边距,或视图是否不愿意拉伸其核心内容(比方说,contentMode属性设为“缩放”的UIImageView控件是否不愿意拉伸其图像)。开发者可以通过setContentCompressionResistancePriority:forAxis:及setContentHuggingPriority:forAxis:方法按坐标轴来设置视图的这两种优先级。

    2、对齐矩形

    约束系统所采用的布局办法与手动排版时所用的框架不同。框架描述的视图摆放的位置及视图的大小,而约束系统的排布视图时,则使用一个与之相关的几何概念,即对齐矩形。

    在创建复杂的视图时,开发者可能会引入一些视觉上的装饰效果,例如阴影、边缘高亮、镜像以及雕刻线条等。这些特性通常是以子视图或子层的形式添加到视图里的。在添加这些物件的过程中,视图的框架及其完整范围也会随之不断变大。

    与frame不同,视图的对去矩形仅仅局限于核心视觉原件。把新的物件添加到主视图并不会影响他的大小。这个示意图带有阴影效果和徽章图样,阴影效果位于主视图的后方,而徽章则在视图右上角。排布这个视图的时候,Auto Layout只会把核心原件同其他视图相对齐。


    把这个对去的矩形和示意图里的那个举行比较一下。那个矩形把所有视觉装饰物都包含在内了,于是,它超出了Auto Layout系统在对齐这个视图时所应参考的边界。那个矩形把视图的所有视觉原件都涵盖进来了。假如按照此矩形来排版,那么这些装饰物可能会干扰排列视图位置时所参照的一些特征。

    Auto Layout系统是根据对齐矩形来排布视图位置的,而不是根据框架属性,这样可以确保排版时所参照的关键信息准确无误。

    声明对去矩形

    在构建带有装饰物的视图时,开发者应该把详细的几何特征告诉Auto Layout系统。如果自己的视图使用了阴影或镜像效果等装饰物,那么可以在视图类里实现alignmentRectForFrame:方法,并返回精确的对齐矩形。

    该方法接受一个参数,也就是框架。该参数表示视图所居的目标框架。示意图中的矩形。那个矩形所代表的框架就涵盖了这个视图,这其中也包括附着在视图上的装饰物。开发者应该根据那个目标框架以及视图中所嵌入的原件来计算出精确的对齐矩形。

    此方法所返回的CGRect值指明了视图的核心视觉内容所处的那个矩形,它通过就是主视图对象本身的框架,而不包括作为子视图或CALayer的子层添加到视图中的那些装饰物。

    如果要对视图执行坐标变换,那么请记住一并实现frameForAlignmentRect:方法。该方法描述的是反向关系,也就是根据传入的对齐矩形来算出可以完整包含所有装饰物的框架。我们会以传入的那个对齐矩形为基础扩大其边界,使之能够把视图里的所有装饰物都涵盖进来。

0 0
原创粉丝点击