ios 约束(五)

来源:互联网 发布:ubuntu删除谷歌输入法 编辑:程序博客网 时间:2024/05/18 01:12

1、用格式字符串将试图对齐并灵活调整其尺寸

    通过约束规则,我们很容易就能指定视图的对齐方式:

    1、“H:|[self]”、“H:[self]|”、“V:[self]|”、“V:|[self]”这4种格式字符串分别产生左对齐、右对齐、顶部对齐及底端对齐的效果。

    2、向上述字符串中添加表示尺寸关系的谓词,即可实现拉伸至左边界、拉伸至右边界等效果:“H:|[self(>=0)]”、“H:[self(>=0)]|”、“V:|[self(>=0)]”、“V:[self(>=0)]|”。

    3、如果再添一条竖线,那么就表示在整条坐标轴方向上面拉伸,也就是令视图从左至右或从上至下跨越整个上级视图:“H:|[self(>=0)]|”或“V:|[self(>=0)]|” 。

    4、可以添加连字符,以便在拉伸本视图的时候,给它的边界与上级视图的边界之间留出一些空隙:“H:|-[self(>=0)]-|”、“V:|-[self(>=0)]-|”。

2、处理约束规则的流程

    系统要经过多个阶段的处理,才能把视图内容显示出来。引入Auto Layout机制之前,这个过程分为两个阶段,即布局阶段与渲染阶段。而Auto Layout机制则在这两个传统的阶段之前,又添加了约束阶段。

    开发者可以实现layoutSubviews方法,以便在布局阶段修改视图里各个子视图的几何特征。当iOS认定某视图的布局已经无效时,就会调用该方法,开发者可在其中手动更新子视图的排布方式。除了系统自动调用之外,开发者可以手工调用setNeedsLayout或layoutIfNeeded方法来请求重新排版。前者是比较温和的请求,iOS系统会把很多这样的请求合并起来,然后再适当的时机调用layoutSubviews方法。而后者则更为迫切,调用了它之后,系统几乎立刻就会执行layoutSubviews。

    在渲染阶段,开发者可通过实现drawRect:方法来完全控制视图UI的绘制。当系统认定视图内容已经无效时,它会调用drawRect:方法,以便对视图进行底层绘制。需要改变渲染内容的时候,开发者可以通过setNeedsDisplay及setNeedsDisplayInRect:方法请求视图重新绘制它自己,这两者都会触发drawRect:。

    有了Auto Layout机制之后,上述两个阶段前面还会多出一个约束阶段。通过实现updateConstraints方法,我们可在该阶段创建并更新Auto Layout系统所使用的约束规则。与布局阶段相似,iOS系统可以自行判定某个视图的约束规则已经无效,从而开始执行约束阶段,而另一方面,开发者也可以手动触发此过程,相关的两个方法叫做setNeedUpdateConstraints及updateConstraintsIfNeeded,其名称与行为与刚才说的那两组方法类似。

    如果复写了视图的updateConstraints方法,那么务必要在该方法返回之前调用[super updateConstraints]。待约束阶段结束之后,Auto Layout会适当计算出视图内所有子视图的几何特征。

    没完成一个阶段,系统就会进入下一阶段。也就是说,执行完约束阶段之后,系统会执行布局阶段,而执行完布局阶段,又会执行渲染阶段。

    这种阶段处理方式给我们一些意想不到的机会。在执行布局阶段的时候,系统已经在约束阶段中吧所有约束规则都计算好了,并且已经根据这些规则设定了视图的几何特征。而在布局阶段,则可以用一种与约束规则相违背的方式继续修改视图的几何特征。另外,也可以根据由约束规则所产生的几何特征来决定视图最终的样貌。由于系统在上个阶段已经把约束规则算好了,所以本阶段对视图样貌所做的修改会一直保留到下一轮约束阶段为止。请勿在布局阶段修改约束规则,否则系统又会触发相关方法来更新约束规则,从而使程序在约束阶段与布局阶段之间陷入无限循环。

    大部分情况下都用不到这些“挂钩”方法。不过在偶尔用到它们时,这些方法会展现出强大的灵活度与控制力。

3、管理约束规则

    无论约束规则是如何创建出来的,它们都属于NSLayoutConstraint类。开发者可以通过addConstraint:方法给视图逐条添加约束规则,也可以把多条规则放在数组里,并通过addConstraint:实例方法将其添加到视图里面。在日常开发中,我们经常会把很多约束规则一并保存在某个数组里。

    存放约束规则的视图自然应该是离规则所涉及的各视图最近的那个共同祖先。在其身上装配约束规则的视图必须是规则里各个视图的共同祖先。我们可以针对NSLayoutConstraint编写category,并在其中实现一个方法,用程序代码吧该规则自动装配到正确的视图上面。

    开发者可以随时添加并移除约束规则。removeConstraint:及removeConstraints:方法分别可以从给定的视图中移除一条约束规则或一组约束规则。由于这两个方法是局域NSLayoutConstraint对象来运作的,所以它的执行效果可能与开发者所想的不符。

    比方说,我们已经构建了一条居中的约束规则,并将其添加到视图里面了。如果现在又构建了一条与之等效的约束规则,然后通过removeConstraint:来移除它,那么你会发现该规则并没有从视图中删掉。这两条约束规则虽然等效,但并不是完全相同的两个对象。下列代码演示了这个问题:

    如果执行上面这两个方法调用,那么self.view实例中就会含有一开始所构建的那条约束规则,但是removeConstraint:方法却会遭到忽略。移除不归该视图所拥有的约束规则是没有效果的。

    有两种解决办法。一种是把开头添加的那条约束规则保存到局部变量里。比如可以写成下面这样:

  [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_textfield attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];    [self.view removeConstraint:[NSLayoutConstraint constraintWithItem:_textfield attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

    另一种是比较已有的约束规则与待移除的约束规则,并把数值相符者从视图里删掉。

    具体采用哪种办法要看约束规则是静态的还是动态的。如果将来可能要移除某条约束规则,那么可将保存到局部变量中,以便稍后移除。

    管理约束规则时,应注意下面几点:

   NSLayoutConstraint *myConstraint = [NSLayoutConstraint constraintWithItem:_textfield attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];    [self.view removeConstraint:myConstraint];

    1、可以在UIView实例上面添加会移除约束规则。与之相关的几个核心方法是:addConstraint:(addConstraints:)、removeConstraint:(removeConstraints:)及constraints。constraints方法会返回包含所有约束规则的数组。

    2、约束规则的使用范围并不局限于容器视图,几乎所有视图都可以施加约束规则。(通过名为requiresConstraintBasedLayout的类方法,我们可以知道这种视图类是不是必须放在基于约束的布局系统里才能够正常运作。)

    3、如果要以编程的方式为子视图施加约束规则,那么把子视图的translatesAutoresizingMaskIntoConstraints属性关掉。

0 0