Autolayout---代码和拉线

参考:http://www.onevcat.com/2012/09/autoayout/


手动使用API添加约束


/* Create constraints explicitly.  Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant" 

 If your equation does not have a second view and attribute, use nil and NSLayoutAttributeNotAnAttribute.

 */

+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

这个类方法遵循一个计算公式:view1.attr1 = view2.attr2 * multiplier + constant"  如果没有参照的那个view(view2)的话就直接传nil和NSLayoutAttributeNotAnAttribute.主要用来 2个view之间的关系限制

比如说我想限制

button1.centerX = button2.centerX

[NSLayoutConstraint constraintWithItem:button1
                           attribute:NSLayoutAttributeCenterX
                             relatedBy:NSLayoutRelationEqual
                                toItem:button2
                             attribute:NSLayoutAttributeCenterX
                            multiplier:1.0f
                              constant:0]

创建好了constrait要添加到哪里去呢

在创建约束之后,需要将其添加到作用的view上。UIView(当然NSView也一样)加入了一个新的实例方法:

  • -(void)addConstraint:(NSLayoutConstraint *)constraint; 用来将约束添加到view。在添加时唯一要注意的是添加的目标view要遵循以下规则:

  • 对于两个同层级view之间的约束关系,添加到他们的父view上

* 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上

* 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上

刷新

可以通过-setNeedsUpdateConstraints和-layoutIfNeeded两个方法来刷新约束的改变,使UIView重新布局。这和CoreGraphic的-setNeedsDisplay一套东西是一样的~

举个例子来看看
Autolayout---代码和拉线_第1张图片
    self.view2 = [[UIView alloc] initWithFrame:self.view1.frame];
    self.view2.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.view2];
    // 这句话别忘了 要去掉系统的constraint
    self.view2.translatesAutoresizingMaskIntoConstraints = NO;
    // y对齐
    NSLayoutConstraint *centerYConstrait = [NSLayoutConstraint constraintWithItem:self.view2
                                                                       attribute:NSLayoutAttributeCenterY
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.view1
                                                                       attribute:NSLayoutAttributeCenterY
                                                                      multiplier:1
                                                                        constant:0];
    // view1的右边 -10-view2的左边
    NSLayoutConstraint *horizontalSpaceConstrait = [NSLayoutConstraint constraintWithItem:self.view2
                                                                                attribute:NSLayoutAttributeLeading
                                                                                relatedBy:NSLayoutRelationEqual
                                                                                   toItem:self.view1
                                                                                attribute:NSLayoutAttributeTrailing
                                                                               multiplier:1
                                                                                 constant:10];
    // 高度
    NSLayoutConstraint *heightConstrait = [NSLayoutConstraint constraintWithItem:self.view2
                                                                       attribute:NSLayoutAttributeHeight
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.view1
                                                                       attribute:NSLayoutAttributeHeight
                                                                      multiplier:1
                                                                        constant:0];
    // 宽度
    NSLayoutConstraint *widthConstrait = [NSLayoutConstraint constraintWithItem:self.view2
                                                                      attribute:NSLayoutAttributeWidth
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:self.view1
                                                                      attribute:NSLayoutAttributeWidth
                                                                     multiplier:1
                                                                       constant:0];
    [self.view addConstraints:@[centerYConstrait, horizontalSpaceConstrait, widthConstrait,heightConstrait]];
Autolayout---代码和拉线_第2张图片
如果是直接在storyboard拉的话就简单拉


Autolayout---代码和拉线_第3张图片

Visual Format Language 可视格式语言


/* Create an array of constraints using an ASCII art-like visual format string.

 */

+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;

先推荐http://constraints.icodeforlove.com/这个网站 牛b 好用

Github上一些好用的Autolayout第三方库

  • Masonry
  • UIView AutoLayout

UIKit团队这次相当有爱,估计他们自己也觉得新加约束的API名字太长了,因此他们发明了一种新的方式来描述约束条件,十分有趣。这种语言是对视觉描述的一种抽象,大概过程看起来是这样的:

accept按钮在cancel按钮右侧默认间距处

最后使用VFL(Visual Format Language)描述变成这样:

[NSLayoutConstraint constraintsWithVisualFormat:@"[cancelButton]-[acceptButton]" 
                                        options:0 
                                        metrics:nil 
                                          views:viewsDictionary];

其中viewsDictionary是绑定了view的名字和对象的字典,对于这个例子可以用以下方法得到对应的字典:

UIButton *cancelButton = ...  
UIButton *acceptButton = ...  
viewsDictionary = NSDictionaryOfVariableBindings(cancelButton,acceptButton);  

生成的字典为

{ acceptButton = ""; cancelButton = ""; }

在view名字后面添加括号以及连接处的数字可以赋予表达式更多意义,以下进行一些举例:

  • [cancelButton(72)]-12-[acceptButton(50)]
    • 取消按钮宽72point,accept按钮宽50point,它们之间间距12point
  • [wideView(>=60@700)]
    • wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)
  • V:[redBox][yellowBox(==redBox)]
    • 竖直布局,先是一个redBox,其下方紧接一个宽度等于redBox宽度的yellowBox
  • H:|-[Find]-[FindNext]-[FindField(>=20)]-|
    • 水平布局,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线'|‘ 表示superview的边缘)
举个例子来看看

我要一个 左边距离self.view 100  顶部距离self.view 100 自身高度宽度都是200的view3

 UIView *view3 = self.view2;
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[view3]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view3)]];
    
    // align self.view2 from the top
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[view3]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view3)]];
    
    // width constraint
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view3(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view3)]];
    
    // height constraint
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view3(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view3)]];

也可以把水平(垂直)方向的合并起来

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[view3(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view3)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[view3(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view3)]];


多个View对齐 算高度

    UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 100, 100)];
    view1.backgroundColor = [UIColor redColor];
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:view1];
    
    UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 100, 100)];
    view2.backgroundColor = [UIColor yellowColor];
    view2.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:view2];
    
    UIView *view3 = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 100, 100)];
    view3.backgroundColor = [UIColor greenColor];
    view3.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:view3];
    
    
     NSString *verticalConstraintstr = @"H:|-space-[view1(viewWidth)]-(space)-[view2(viewWidth)]-(space)-[view3(viewWidth)]-(>=10)-|";
    NSDictionary *views = @{@"view1":view1, @"view2": view2, @"view3":view3};
    NSDictionary *metrics = @{@"viewWidth":@"20", @"space":@"10"};
    NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:verticalConstraintstr
                                                                                      options:NSLayoutFormatAlignAllCenterY
                                                                                      metrics:metrics
                                                                                        views:views];
      [self.view addConstraints:verticalConstraints];
    NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view1 attribute:NSLayoutAttributeHeight multiplier:1.2 constant:0];
    NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeHeight multiplier:1.2 constant:0];
    NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view3 attribute:NSLayoutAttributeHeight multiplier:1.2 constant:0];
    
    [self.view addConstraints:@[constraint1, constraint2, constraint3]];


Autolayout---代码和拉线_第4张图片


改天再说说scrollview 和 如何debug autolayout那一大堆警告


你可能感兴趣的:(iOS开发系列,AutoLayout)