天天看点

iOS 自动布局 Masonry1. What's wrong with NSLayoutConstraints ?2. Prepare to meet your Maker !3. Not all things are created equal4. Learn to prioritize5. Composition, composition, composition

开源项目 Masonry 旨在让自动布局(Auto Layout)的代码更简洁、可读性更强。

Masonry ,“一个轻量级的布局框架,采用更优雅的语法封装自动布局”,不需要使用 XIB 和 Storyboard. 它的创造者Jonas Budelmann 论证了尽管自动布局很强大,但它很快就变得冗长而不可读。

Masonry是一种领域特定语言(DSL),为自动布局的所有功能提供便捷的方法,包括建立和修改约束、存取属性、设置优先级以及调试支持。

1. What's wrong with NSLayoutConstraints ?

NSLayoutConstraints 的繁琐之处,代码如下:

UIView *superview = self;

UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
view1.backgroundColor = [UIColor greenColor];
[superview addSubview:view1];

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[superview addConstraints:@[

	//view1 constraints
    [NSLayoutConstraint constraintsntWithItem:view1
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.0
                                  constant:padding.top],


    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeLeft
                                multiplier:1.0
                                  constant:padding.left],


    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0
                                  constant:-padding.bottom],


    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeRight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeRight
                                multiplier:1
                                  constant:-padding.right],

 ]];
           

2. Prepare to meet your Maker !

MASConstraintMaker 的简洁之处,代码如下:

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
    make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
    make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];
           

或者更简洁:

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(superview).with.insets(padding);
}];
           

3. Not all things are created equal

并非所有的约束都用 equal 创建的,例如:

.equalTo 相当于 NSLayoutRelationEqual

.lessThanOrEqualTo 相当于 NSLayoutRelationLessThanOrEqual

.greaterThanOrEqualTo 相当于 NSLayoutRelationGreaterThanOrEqual
           

3.1 MASViewAttribute

常用属性:

@property (nonatomic, strong, readonly) MASConstraint *left; // 左侧

@property (nonatomic, strong, readonly) MASConstraint *top; // 顶部

@property (nonatomic, strong, readonly) MASConstraint *right; // 右侧

@property (nonatomic, strong, readonly) MASConstraint *bottom; // 底部

@property (nonatomic, strong, readonly) MASConstraint *leading; // 首部

@property (nonatomic, strong, readonly) MASConstraint *trailing; // 尾部

@property (nonatomic, strong, readonly) MASConstraint *width; // 宽

@property (nonatomic, strong, readonly) MASConstraint *height; // 高

@property (nonatomic, strong, readonly) MASConstraint *centerX; // 中心点x

@property (nonatomic, strong, readonly) MASConstraint *centerY; // 中心点y

@property (nonatomic, strong, readonly) MASConstraint *baseline; // 文本基线
           

3.2 UIView/NSView

如果你想要 view.left 大于或等于 label.left, 下面两个约束都可以实现:

//these two constraints are exactly the same
make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);
           

3.3 NSNumber

自动布局允许宽高设置为常量。如果你想给一个视图的宽度设置最小值和最大值,可以传递数字,如下:

//width >= 200 && width <= 400
make.width.greaterThanOrEqualTo(@200);
make.width.lessThanOrEqualTo(@400)
           

但是,自动布局不允许 left, right, centerY 等属性变量设置常量。因此,若给这类属性传 NSNumber 类型的参数,Masonry 会返回父视图相关的约束,例如:

//creates view.left = view.superview.left + 10
make.left.lessThanOrEqualTo(@10)
           

除了用 NSNumber, 也可以用基元 (primitives) 和结构体来创建常量,例如:

make.top.mas_equalTo(42);
make.height.mas_equalTo(20);
make.size.mas_equalTo(CGSizeMake(50, 100));
make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));
make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));
           

3.4 NSArray

也可以用上述类型任意组合成的数组,例如:

make.height.equalTo(@[view1.mas_height, view2.mas_height]);
make.height.equalTo(@[view1, view2]);
make.left.equalTo(@[view1, @100, view3.right]);
           

4. Learn to prioritize

划分优先级。

.priority: 指定具体的优先级。

.priorityHigh 相当于 UILayoutPriorityDefaultHigh

.priorityMedium 介于高和低之间。

.priorityLow 相当于 UILayoutPriorityDefaultLow
           

优先级可以附加到一个约束链的最后,例如:

make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow();

make.top.equalTo(label.mas_top).with.priority(600);
           

5. Composition, composition, composition

Masonry 提供了几个很方便的方法可以同时创建多个约束,这就是 MASCompositeConstraints.

5.1 edges

// make top, left, bottom, right equal view2
make.edges.equalTo(view2);

// make top = superview.top + 5, left = superview.left + 10,
//      bottom = superview.bottom - 15, right = superview.right - 20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))
           

5.2 size

// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel)

// make width = superview.width + 100, height = superview.height - 50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))
           

5.3 center

// make centerX and centerY = button1
make.center.equalTo(button1)

// make centerX = superview.centerX - 5, centerY = superview.centerY + 10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))
           

PS: 还有一部分内容未涉及到,这里只写了本人平时用到的,详情可查看原文。

GitHub 原文链接: https://github.com/SnapKit/Masonry

参考链接:

1.  Masonry简单使用

2. Masonry与iOS自动布局

3. Masonry介绍与使用实践:快速上手Autolayout