Masonry布局

2021-03-01  本文已影响0人  Xl_Lee

设定上下左右内边距

  1. 约束是相对于参照试图坐标系。也可以单独写针对参照试图的约束方向
  2. equalTo()针对的的是对象,例如试图对象,试图的约束对象
  3. edges内边距,针对参照试图的内边距,四个方向大于0代表相对于参照试图内部展示。
  4. offset(基本数据类型),如果是水平方向,设置的值大于0,是相对于参照试图的右边布局,否则是左方布局。
    如果是竖直方向,设置的值大于0,是相对于参考试图的下方布局,否则是上方布局。
  5. mas_equalTo(),可以写基本数值类型,也可以使用参照对象等。
- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *contentView         = [UIView new];
    contentView.backgroundColor = [UIColor redColor];
    [self.view addSubview:contentView];
    if (arc4random() % 2) {
        // 直接设置edges
        [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            make.edges.mas_equalTo(UIEdgeInsetsMake(10 + 64.f, 10, 10, 10));
        }];
        
    } else {
        
        // // 设置 left, right, bottom, top
        UIView *supperView = self.view;
        [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
            
//            make.top.equalTo(supperView.mas_top).offset(10 + 64);
//            make.left.equalTo(supperView.mas_left).offset(10);
//            make.bottom.equalTo(supperView.mas_bottom).offset(-10);
//            make.right.equalTo(supperView.mas_right).offset(-10);
            make.top.equalTo(supperView).offset(10 + 64);
            make.left.equalTo(supperView).offset(10);
            make.bottom.equalTo(supperView).offset(-10);
            make.right.equalTo(supperView).offset(-10);
        }];
    }
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 22.47.34.png

设定具体尺寸

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIView *redView         = [UIView new];
    redView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.5f];
    [self.view addSubview:redView];
    
    UIView *yellowView         = [UIView new];
    yellowView.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.5f];
    [self.view addSubview:yellowView];
    
    UIView *supperView = self.view;
    
    // 设定尺寸100x100,距离左边10,下边-10
    [redView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(100, 100));
        make.left.equalTo(supperView.mas_left).offset(10);
        make.bottom.equalTo(supperView.mas_bottom).offset(-10);
    }];
    
    // 设定尺寸100x100,居中
    [yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(100, 100));
        make.center.equalTo(supperView);
    }];
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.04.29.png

根据相对性设置宽高

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIView *redView         = [UIView new];
    redView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.5f];
    [self.view addSubview:redView];
    
    UIView *yellowView         = [UIView new];
    yellowView.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.5f];
    [self.view addSubview:yellowView];
    
    UIView *supperView = self.view;
    
    [redView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        // 距离左边10
        make.left.equalTo(supperView.mas_left).offset(10);
        
        // 距离底部-10
        make.bottom.equalTo(supperView.mas_bottom).offset(-10);
        
        // 高度为 supperView 高度一半
        make.height.equalTo(supperView.mas_height).multipliedBy(0.5);
        
        // 宽度为 yellowView 的 1/4
        make.width.equalTo(yellowView.mas_width).multipliedBy(0.25);
    }];
    
    [yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        // 距离右边-10
        make.right.equalTo(supperView.mas_right).offset(-10);
        
        // 距离底部-10
        make.bottom.equalTo(supperView.mas_bottom).offset(-10);
        
        // 高度为 redView 1/2
        make.height.equalTo(redView.mas_height).multipliedBy(0.5);
        
        // 距离 redView 右边距离为10
        make.left.equalTo(redView.mas_right).offset(10.f);
    }];
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.08.10.png

根据子view宽高确定父view宽高

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // 载体view
    UIView *contentView           = [[UIView alloc] init];
    contentView.layer.borderColor = [UIColor redColor].CGColor;
    contentView.layer.borderWidth = 0.5f;
    [self.view addSubview:contentView];
    
    // 红色view
    UIView *redView         = [UIView new];
    redView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.75f];
    [contentView addSubview:redView];
    
    // 绿色view
    UIView *greenView         = [UIView new];
    greenView.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.75f];
    [contentView addSubview:greenView];
    
    if (arc4random() % 2) {
     
        /* ---------------------- */
        /* lessThanOrEqualTo的使用 */
        /* ---------------------- */
        
        [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            make.center.equalTo(self.view);
        }];
        
        UIView *supperView = contentView;
        
        [redView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            // 设定尺寸
            make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
            
            // 左边与 supperView 左边对齐
            make.left.equalTo(supperView.mas_left);
            
            // 顶部与 supperView 顶部对齐
            make.top.equalTo(supperView.mas_top);
            
            // 底部小于或者等于 supperView 的底部
            make.bottom.lessThanOrEqualTo(supperView.mas_bottom);
        }];
        
        [greenView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            // 设定尺寸
            make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
            
            // 左边距离 redView 右边距离10
            make.left.equalTo(redView.mas_right).offset(10);
            
            // 顶部与 supperView 顶部对齐
            make.top.equalTo(supperView.mas_top);
            
            // 右边与 supperView 右边对齐
            make.right.equalTo(supperView.mas_right);
            
            // 底部小于或者等于 supperView 的底部
            make.bottom.lessThanOrEqualTo(supperView.mas_bottom);
        }];
        
    } else {
        
        /* ------------------------- */
        /* greaterThanOrEqualTo的使用 */
        /* ------------------------- */
        
        [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            make.center.equalTo(self.view);
            
            // 底部大于或者等于 redView 的底部
            make.bottom.greaterThanOrEqualTo(redView.mas_bottom);
            
            // 底部大于或者等于 greenView 的底部
            make.bottom.greaterThanOrEqualTo(greenView.mas_bottom);
        }];
        
        UIView *supperView = contentView;
        
        [redView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            // 设定尺寸
            make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
            
            // 左边与 supperView 左边对齐
            make.left.equalTo(supperView.mas_left);
            
            // 顶部与 supperView 顶部对齐
            make.top.equalTo(supperView.mas_top);
        }];
        
        [greenView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            // 设定尺寸
            make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
            
            // 左边距离 redView 右边距离10
            make.left.equalTo(redView.mas_right).offset(10);
            
            // 顶部与 supperView 顶部对齐
            make.top.equalTo(supperView.mas_top);
            
            // 右边与 supperView 右边对齐
            make.right.equalTo(supperView.mas_right);
        }];
    }
}

Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.11.21.png

修改约束的情形

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIView *redView         = [UIView new];
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];
    
    UIView *supperView = self.view;
    
    if (arc4random() % 2) {
        
        /* --------------------------- */
        /* mas_updateConstraints更新约束 */
        /* --------------------------- */
        
        [redView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            // 距离左边10
            make.left.equalTo(supperView.mas_left).offset(10.f);
            
            // 距离底部-10
            make.bottom.equalTo(supperView.mas_bottom).offset(-10.f);
            
            // 设定尺寸100x100
            make.size.mas_equalTo(CGSizeMake(100, 100));
        }];
        
        [GCDQueue executeInMainQueue:^{
            
            // 更新约束
            [redView mas_updateConstraints:^(MASConstraintMaker *make) {
                
                // 重新设定尺寸为200x200
                make.size.mas_equalTo(CGSizeMake(200, 200));
            }];
            
        } afterDelaySecs:2.f];
        
    } else {
        
        /* ---------------------- */
        /* MASConstraint对象更新约束 */
        /* ---------------------- */
        
        MASConstraint __block *constraint = nil;
        
        [redView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            // 距离左边10
            make.left.equalTo(supperView.mas_left).offset(10.f);
            
            // 距离底部-10
            make.bottom.equalTo(supperView.mas_bottom).offset(-10.f);
            
            // (获取设定尺寸的约束) 设定尺寸100x100
            constraint = make.size.mas_equalTo(CGSizeMake(100, 100));
        }];
        
        [GCDQueue executeInMainQueue:^{
            
            // 重新设定尺寸为200x200
            constraint.mas_equalTo(CGSizeMake(200, 200));
            
        } afterDelaySecs:2.f];
    }
}

Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.25.19.png Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.25.42.png

cell自动算高度-版本1

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
// 通知中心(检测屏幕旋转)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationEvent:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
//    
    // 数据源
    self.datas = [NSMutableArray array];
    [self.datas addObject:@"篱笆墙是个历史的产物,它的产生和消失,是农村发展、农民生活变化的见证。"];
    [self.datas addObject:@"漆太太,是陕西陇县人,到底姓什么,也真没有知根知底的。"];
    [self.datas addObject:@"那一年,漆太太的丈夫随渔船下海,突然遇到狂风暴雨,连人带船沉没了大海,从此没有消息。"];
    [self.datas addObject:@"那时虽说是大集体,可是对五保户,那是照顾有加。凡是生产队分东西,如粮食、柴草,蔬菜等,都是要挑最好的先给漆太太送到家。"];
    [self.datas addObject:@"围绕村子里这道最后的篱笆墙,生发了许多故事,至今还流传在故乡的巷子里,铭刻在村里人的记忆中。"];
    
    // tableView
    self.tableView            = [[UITableView alloc] init];
    self.tableView.delegate   = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
    
    // 注册cell
    [self.tableView registerClass:[CellAutoHeightInfoCell class] forCellReuseIdentifier:@"CellAutoHeightInfoCell"];
    
    // 添加tableView约束
    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.edges.mas_equalTo(UIEdgeInsetsMake(0, 0, 0, 0));
    }];
    
    // 设定预估行高
    self.tableView.estimatedRowHeight  = 45.f;
    self.tableView.rowHeight           = UITableViewAutomaticDimension;
}

#pragma mark - UITableViewDelegate, UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    return self.datas.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    CellAutoHeightInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellAutoHeightInfoCell" forIndexPath:indexPath];
    cell.data                    = self.datas[indexPath.row];
    [cell loadContent];
    
    return cell;
}

#pragma mark - notificationEvent
- (void)notificationEvent:(NSNotification *)notification {
    if ([notification.name isEqualToString:UIApplicationDidChangeStatusBarOrientationNotification]) {
        // 屏幕刷新后重新加载cell
        [self.tableView reloadData];
    }
}

CustomCellAutoHeightInfoCell

@interface CustomCellAutoHeightInfoCell ()

@property (nonatomic, strong) UIImageView *iconImageView;
@property (nonatomic, strong) UILabel     *label;
@property (nonatomic, strong) UIView      *lineView;

@end

@implementation CustomCellAutoHeightInfoCell

- (void)buildSubview {
    
    self.iconImageView                 = [UIImageView new];
    self.iconImageView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5f];
    [self.contentView addSubview:self.iconImageView];
    
    self.label               = [UILabel new];
    self.label.numberOfLines = 4;
    [self.contentView addSubview:self.label];
    
    self.lineView                 = [UIView new];
    self.lineView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.25f];
    [self.contentView addSubview:self.lineView];
    
    UIView *supperView = self.contentView;
    
    [self.iconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.top.equalTo(supperView.mas_top).offset(10);
        make.left.equalTo(supperView.mas_left).offset(10);
        make.size.mas_equalTo(CGSizeMake(50.f, 50.f));
        
        make.bottom.lessThanOrEqualTo(supperView.mas_bottom).offset(-10.f);
    }];
    
    [self.label mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.top.equalTo(supperView.mas_top).offset(10);
        make.left.equalTo(self.iconImageView.mas_right).offset(10.f);
        make.right.equalTo(supperView.mas_right).offset(-10.f);
        
        make.bottom.lessThanOrEqualTo(supperView.mas_bottom).offset(-10.f);
    }];
    
    [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.bottom.equalTo(supperView.mas_bottom);
        make.left.equalTo(self.contentView.mas_left).offset(10.f);
        make.right.equalTo(self.contentView.mas_right).offset(-10.f);
        make.height.equalTo(@1);
    }];
}

- (void)loadContent {
    
    // 更新约束
    [self.lineView mas_updateConstraints:^(MASConstraintMaker *make) {
        
        if (self.indexPath.row % 2) {
            
            make.left.equalTo(self.contentView.mas_left).offset(50.f);
            make.right.equalTo(self.contentView.mas_right).offset(-50.f);
            
        } else {
            
            make.left.equalTo(self.contentView.mas_left).offset(10.f);
            make.right.equalTo(self.contentView.mas_right).offset(-10.f);
        }
    }];
    
    // 设定最大行宽
    self.label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 10 - 50 - 20;
    
    // 加载数据
    self.label.attributedText = [NSAttributedString attributedStringWithString:self.data config:^(NSMutableArray<AttributedStringConfig *> *configs) {
        
        NSMutableParagraphStyle *style = [NSMutableParagraphStyle new];
        style.lineSpacing              = 5.f;
        
        [configs addObject:[ParagraphAttributeConfig configWithParagraphStyle:style]];
        [configs addObject:[FontAttributeConfig configWithFont:[UIFont systemFontOfSize:12.f]]];
    }];;
}

- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
    
    [super setHighlighted:highlighted animated:animated];
    
    // 更新约束值
    [self.iconImageView mas_updateConstraints:^(MASConstraintMaker *make) {
        
        make.left.equalTo(self.contentView.mas_left).offset(highlighted ? 15 : 10);
    }];
    
    [UIView animateWithDuration:0.25f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        
        [self.contentView layoutIfNeeded];
        self.contentView.backgroundColor = highlighted ? [[UIColor grayColor] colorWithAlphaComponent:0.15f] : [UIColor whiteColor];
        
    } completion:nil];
}
image.png image.png

延展缩放

@interface ExpendLayoutCell ()

@property (nonatomic, strong) UIView         *lineView;
@property (nonatomic, strong) UILabel        *label;
@property (nonatomic, strong) MASConstraint  *constraint;

@end

@implementation ExpendLayoutCell

- (void)buildSubview {
    
    self.lineView                 = [UIView new];
    self.lineView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5f];
    [self.contentView addSubview:self.lineView];
    
    [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.mas_equalTo(0);
        make.bottom.mas_equalTo(0);
        make.right.mas_equalTo(0);
        make.height.mas_equalTo(0.5);
    }];
    
    self.label               = [UILabel new];
    self.label.numberOfLines = 0;
    [self.contentView addSubview:self.label];
    
    [self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
        
        make.left.mas_equalTo(10.f);
        make.top.mas_equalTo(10.f);
        make.right.mas_equalTo(-10.f);
        make.height.mas_equalTo([UIFont labelFontSize]);
    }];
}

- (void)loadContent {
    
    self.label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
    
    ExpendLayoutCellModel *model = self.data;
    self.label.text              = model.string;
    
    if (model.expend == YES) {
        
        [self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
            
            make.left.mas_equalTo(10.f);
            make.top.mas_equalTo(10.f);
            make.right.mas_equalTo(-10.f);
            make.bottom.mas_lessThanOrEqualTo(-10.f);
        }];
        
    } else {
        
        [self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
            
            make.left.mas_equalTo(10.f);
            make.top.mas_equalTo(10.f);
            make.right.mas_equalTo(-10.f);
            make.height.mas_equalTo([UIFont labelFontSize]);
        }];
    }
}

- (void)selectedEvent {
    
    ExpendLayoutCellModel *model = self.data;

    if (model.expend == YES) {
        
        [self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
            
            make.left.mas_equalTo(10.f);
            make.top.mas_equalTo(10.f);
            make.right.mas_equalTo(-10.f);
            make.height.mas_equalTo([UIFont labelFontSize]);
        }];
        
    } else {
        
        [self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
            
            make.left.mas_equalTo(10.f);
            make.top.mas_equalTo(10.f);
            make.right.mas_equalTo(-10.f);
            make.bottom.mas_lessThanOrEqualTo(-10.f);
        }];
    }
    
    model.expend = !model.expend;
    
    // 执行动画
    [UIView animateWithDuration:0.25f animations:^{
    
        [self.label.superview layoutIfNeeded];
    }];
    
    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

@end

约束优先级

typedef enum : NSUInteger {
    
    kDeleteOrangeViewButton = 1000,
    kDeleteYellowViewButton,
    
} EPriorityConstraintViewControllerTagValue;

@interface PriorityConstraintViewController ()

@property (nonatomic ,strong) UIView *orangeView;
@property (nonatomic ,strong) UIView *yellowView;
@property (nonatomic ,strong) UIView *greenView;

@end

@implementation PriorityConstraintViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    [self initButtons];
    
    self.orangeView                 = [[UIView alloc] init];
    self.orangeView.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:self.orangeView];
    
    self.yellowView                 = [[UIView alloc] init];
    self.yellowView.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:self.yellowView];
    
    self.greenView                 = [[UIView alloc] init];
    self.greenView.backgroundColor = [UIColor greenColor];
    [self.view addSubview:self.greenView];
    
    // 橘色(作为基准)
    [self.orangeView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.width.height.mas_equalTo(50);
        make.bottom.offset(-10);
        
        make.left.offset(10);
    }];
    
    // 黄色
    [self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.width.height.mas_equalTo(50);
        make.bottom.offset(-10);
        
        // 用优先级来设定满足条件,此处为2种情况
        make.left.equalTo(self.orangeView.mas_right).offset(10).priorityHigh();
        make.left.equalTo(self.view.mas_left).offset(10).priorityMedium();
    }];
    
    // 绿色
    [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.width.height.mas_equalTo(50);
        make.bottom.offset(-10);
        
        // 用优先级来设定满足条件,此处为3种情况
        make.left.equalTo(self.yellowView.mas_right).offset(10).priorityHigh();
        make.left.equalTo(self.orangeView.mas_right).offset(10).priorityMedium();
        make.left.equalTo(self.view.mas_left).offset(10).priorityLow();
    }];
}

- (void)initButtons {

    UIButton *deleteOrangeYellowViewButton = [UIButton buttonWithType:UIButtonTypeSystem];
    deleteOrangeYellowViewButton.tag       = kDeleteOrangeViewButton;
    [deleteOrangeYellowViewButton setTitle:@"删除橘色view" forState:UIControlStateNormal];
    [deleteOrangeYellowViewButton addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:deleteOrangeYellowViewButton];
    
    [deleteOrangeYellowViewButton mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.top.mas_equalTo(64 + 10.f);
        make.left.mas_equalTo(10.f);
    }];
    
    UIButton *deleteYellowViewButton = [UIButton buttonWithType:UIButtonTypeSystem];
    deleteYellowViewButton.tag       = kDeleteYellowViewButton;
    [deleteYellowViewButton setTitle:@"删除黄色view" forState:UIControlStateNormal];
    [deleteYellowViewButton addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:deleteYellowViewButton];
    
    [deleteYellowViewButton mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.top.equalTo(deleteOrangeYellowViewButton.mas_bottom).offset(10.f);
        make.left.mas_equalTo(10.f);
    }];
}

- (void)buttonsEvent:(UIButton *)button {
 
    if (button.tag == kDeleteOrangeViewButton) {
        
        [self.orangeView removeFromSuperview];
        [UIView animateWithDuration:0.5f animations:^{
            
            [self.view layoutIfNeeded];
        }];
        
    } else if (button.tag == kDeleteYellowViewButton) {
        
        [self.yellowView removeFromSuperview];
        [UIView animateWithDuration:0.5f animations:^{
            
            [self.view layoutIfNeeded];
        }];
    }
}

@end
image.png

Install的使用

@interface ConstraintInstallViewController () {
    
    BOOL _isUninstalled;
}

@property (nonatomic, strong) MASConstraint *constraint;

@end

@implementation ConstraintInstallViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    [self initButton];
    
    UIView *redView         = [UIView new];
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];
    
    [redView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.width.height.mas_equalTo(100).priorityMedium();
        make.center.equalTo(self.view);
        
        self.constraint = make.width.height.mas_equalTo(200).priorityHigh();
    }];
}

- (void)initButton {
    
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"uninstall" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
    [button mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.centerX.equalTo(self.view.mas_centerX);
        make.bottom.mas_equalTo(-10);
    }];
}

- (void)buttonsEvent:(UIButton *)button {
    
    if (_isUninstalled == NO) {
        
        _isUninstalled = YES;
        [button setTitle:@"install" forState:UIControlStateNormal];
        [self.constraint uninstall];

        
    } else {
        
        _isUninstalled = NO;
        [button setTitle:@"uninstall" forState:UIControlStateNormal];
        [self.constraint install];
    }
    
    button.enabled = NO;
    
    [UIView animateWithDuration:0.5f animations:^{
        
        [self.view layoutIfNeeded];
        
    } completion:^(BOOL finished) {
        
        button.enabled = YES;
    }];
}

@end
image.png

CompressionResistance

@interface CompressionResistanceViewController ()

@end

@implementation CompressionResistanceViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIButton *button          = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.layer.borderWidth  = 0.5f;
    button.layer.borderColor  = [UIColor blackColor].CGColor;
    button.layer.cornerRadius = 4.f;
    [button setTitle:@"CompressionResistanceViewController" forState:UIControlStateNormal];
    [self.view addSubview:button];
    
    // 重新设定水平方向上button防挤压适配文本宽度的优先级为500,不设定的话,默认值为750
    [button setContentCompressionResistancePriority:500 forAxis:UILayoutConstraintAxisHorizontal];
    
    __block NSString *showString = nil;
    [button mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.center.equalTo(self.view);
        
        // 设置宽度为50,如果优先级低于设定的500,设置的宽度50将失效,如果优先级大于500,设置的宽度50有效
        CGFloat priority = arc4random() % 2 ? 499 : 501;
        make.width.mas_equalTo(50.f).priority(priority);
        
        showString = [NSString stringWithFormat:@"优先级: %.0f %@", priority, priority > 500 ? @"挤压宽度设定有效" : @"挤压宽度设定无效"];
    }];
    
    UILabel *label                = [UILabel new];
    label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
    [self.view addSubview:label];
    [label mas_makeConstraints:^(MASConstraintMaker *make) {
       
        make.left.mas_equalTo(10);
        make.bottom.mas_equalTo(-10);
    }];
    label.text = showString;
}

@end
image.png
image.png

ContentHugging

@interface ContentHuggingViewController ()

@end

@implementation ContentHuggingViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    UIButton *button          = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.layer.borderWidth  = 0.5f;
    button.layer.borderColor  = [UIColor blackColor].CGColor;
    button.layer.cornerRadius = 4.f;
    [button setTitle:@"ContentHuggingViewController" forState:UIControlStateNormal];
    [self.view addSubview:button];
    
    // 重新设定水平方向上button超出宽度适配文本宽度的优先级为500,不设定的话,默认值为250
    [button setContentHuggingPriority:500 forAxis:UILayoutConstraintAxisHorizontal];
    
    __block NSString *showString = nil;
    [button mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.center.equalTo(self.view);
        
        // 设置宽度为300,如果优先级低于设定的500,设置的宽度300将失效,如果优先级大于500,设置的宽度300有效
        CGFloat priority = arc4random() % 2 ? 499 : 501;
        make.width.mas_equalTo(300.f).priority(priority);
        
        showString = [NSString stringWithFormat:@"优先级: %.0f %@", priority, priority > 500 ? @"超出宽度设定有效" : @"超出宽度设定无效"];
    }];
    
    UILabel *label                = [UILabel new];
    label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
    [self.view addSubview:label];
    [label mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.mas_equalTo(10);
        make.bottom.mas_equalTo(-10);
    }];
    label.text = showString;
}

@end

image.png image.png

Layout与Frame混合的自定义view

@interface CustomLayoutMixFrameViewController ()

@end

@implementation CustomLayoutMixFrameViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    if (arc4random() % 2) {
        
        // Frame形式布局
        CustomLayoutView *mixView = [[CustomLayoutView alloc] initWithFrame:CGRectMake(0, 0, Width - 80.f, 100)];
        mixView.center            = self.view.center;
        [self.view addSubview:mixView];
        
        mixView.label.text = @"Frame 脑袋空了半晌后,我突地拿起电话,打电话同领导请假。";
        
    } else {
     
        // Layout形式布局
        CustomLayoutView *mixView = [CustomLayoutView new];
        [self.view addSubview:mixView];
        
        [mixView mas_makeConstraints:^(MASConstraintMaker *make) {
            
            make.center.equalTo(self.view);
            make.left.mas_offset(40.f);
            make.right.mas_offset(-40.f);
            make.height.mas_equalTo(100.f);
        }];
        
        mixView.label.text = @"Layout 脑袋空了半晌后,我突地拿起电话,打电话同领导请假。";
    }
}

@end

@interface CustomLayoutView ()

@end

@implementation CustomLayoutView

- (instancetype)init {
    
    NSLog(@"[CustomLayoutView new]");
    if (self = [super init]) {
        
        [self initSubViews];
    }
    
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    
    NSLog(@"[[CustomLayoutView alloc] initWithFrame:frame]");
    if (self = [super initWithFrame:frame]) {
        
        [self initSubViews];
    }
    
    return self;
}

- (void)initSubViews {
    
    self.layer.borderWidth = 0.5f;
    self.layer.borderColor = [UIColor redColor].CGColor;
    
    if (!self.label) {
        
        // 传统frame模式的label
        self.label                   = [[UILabel alloc] initWithFrame:CGRectZero];
        self.label.layer.borderWidth = 0.5f;
        self.label.numberOfLines     = 0;
        self.label.layer.borderColor = [UIColor greenColor].CGColor;
        self.label.top               = 10.f;
        self.label.left              = 10.f;
        [self addSubview:self.label];
    }
}

- (void)layoutSubviews {
    
    [super layoutSubviews];

    // 只影响frame形式的布局
    self.label.width = self.width - 20.f;
    [self.label sizeToFit];
}

@end

image.png image.png

IntrinsicContent

@interface IntrinsicContentViewController ()

@property (nonatomic, strong) IntrinsicContentSizeView *wrappingView;

@end

@implementation IntrinsicContentViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // http://devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.html
    
    // 通知中心(检测屏幕旋转)
    self.notificationCenter = [DefaultNotificationCenter defaultNotificationCenterWithDelegate:self addNotificationNames:^(NSMutableArray<NSString *> *names) {
        
        [names addObject:UIApplicationDidChangeStatusBarOrientationNotification];
    }];
    
    self.wrappingView = [IntrinsicContentSizeView new];
    self.wrappingView.layer.borderWidth    = 0.5f;
    self.wrappingView.layer.borderColor    = [UIColor redColor].CGColor;
    self.wrappingView                      = self.wrappingView;
    [self.view addSubview:self.wrappingView];
    
    [self.wrappingView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.center.equalTo(self.view);
    }];
    
    self.wrappingView.itemCount               = arc4random() % 100 + 4;
    self.wrappingView.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 100;
    
    // 按钮
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"Change ItemCount" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
    [button mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.bottom.mas_equalTo(-10.f);
        make.left.mas_equalTo(10.f);
    }];
}

- (void)defaultNotificationCenter:(DefaultNotificationCenter *)notification name:(NSString *)name object:(id)object {
    
    if ([name isEqualToString:UIApplicationDidChangeStatusBarOrientationNotification]) {
        
        // 屏幕旋转后重新设置最大宽度
        self.wrappingView.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 100;
    }
}

#pragma mark - 

- (void)buttonsEvent:(UIButton *)button {
    
    self.wrappingView.itemCount = arc4random() % 100 + 4;
}
static const CGSize itemSize = {20, 12};

@implementation IntrinsicContentSizeView

#pragma mark - Setter method.

- (void)setItemCount:(NSInteger)itemCount {
    
    _itemCount = itemCount;
    
    // 删除所有的subView
    while (self.subviews.count) {
        
        [self.subviews.lastObject removeFromSuperview];
    }
    
    // 添加view
    for (int i = 0; i < _itemCount; i++) {
        
        UIView *view         = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemSize.width, itemSize.height)];
        view.backgroundColor = [UIColor colorWithHue:((13 + i * 17) % 255) / 255. saturation:1 brightness:1 alpha:1.0];
        
        // 不支持约束,所有的布局在-layoutSubviews中用setFrame的方式
        view.translatesAutoresizingMaskIntoConstraints = NO;
        [self addSubview:view];
        
        // 显示的文本
        UILabel *label      = [UILabel new];
        label.font          = [UIFont systemFontOfSize:10.f];
        label.text          = [NSString stringWithFormat:@"%d", i + 1];
        label.textAlignment = NSTextAlignmentCenter;
        label.textColor     = [UIColor whiteColor];
        [view addSubview:label];
        
        [label mas_makeConstraints:^(MASConstraintMaker *make) {
            
            make.left.mas_equalTo(0);
            make.top.mas_equalTo(0);
            make.size.mas_equalTo(CGSizeMake(itemSize.width, itemSize.height));
        }];
    }
    
    // 通知布局系统让固有的内容尺寸失效,接下来系统会从intrinsicContentSize方法中读取新的固有的尺寸
    [self invalidateIntrinsicContentSize];
}

- (void)setPreferredMaxLayoutWidth:(CGFloat)width {
    
    // 如果设定的最大宽度与自己的最大宽度相等,则不做任何操作
    if (self.preferredMaxLayoutWidth == width) {
        
        return;
    }
    
    _preferredMaxLayoutWidth = width;
    
    // 通知布局系统让固有的内容尺寸失效,接下来系统会从intrinsicContentSize方法中读取新的固有的尺寸
    [self invalidateIntrinsicContentSize];
}

#pragma mark - Private method.

/**
 根据给定的总宽度,计算每一个子view的frame的尺寸

 @param layoutWidth 给定的宽度
 @param block 每一个子view的frame值
 */
- (void)enumerateItemRectsForLayoutWidth:(CGFloat)layoutWidth usingBlock:(void (^)(CGRect itemRect))block {
    
    CGFloat x = 0;
    CGFloat y = 0;
    
    for (NSUInteger i = 0; i < self.itemCount; i++) {
        
        if (x + itemSize.width > layoutWidth) {
            
            y += itemSize.height;
            x  = 0;
        }
        
        block(CGRectMake(x, y, itemSize.width, itemSize.height));
        
        x += itemSize.width;
    }
}

#pragma mark - Overwrite system method.

- (CGSize)intrinsicContentSize {
    
    if (self.itemCount == 0) {
        
        return CGSizeZero;
    }
    
    __block CGRect totalRect = CGRectNull;
    [self enumerateItemRectsForLayoutWidth:self.preferredMaxLayoutWidth usingBlock:^(CGRect itemRect) {
        
        // 获取融合的rect值
        totalRect = CGRectUnion(itemRect, totalRect);
    }];
    
    return totalRect.size;
}

- (void)layoutSubviews {
    
    [super layoutSubviews];
    
    NSEnumerator *subviewEnumerator = [self.subviews objectEnumerator];
    [self enumerateItemRectsForLayoutWidth:self.preferredMaxLayoutWidth usingBlock:^(CGRect itemRect) {
        
        // 给每一个子view设定尺寸
        [[subviewEnumerator nextObject] setFrame:itemRect];
    }];
}

@end
image.png

BaselineLayoutView

@interface BaselineLayoutViewController ()

@end

@implementation BaselineLayoutViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // BaselineLayoutView 01
    BaselineLayoutView *baseLineView_01 = [BaselineLayoutView baselineLayoutViewWithString:@"不知从什么时候开始,对一片沉寂的冬天,以及纷扬洁白的雪花,生出了一种极其厌恶的情绪。"
                                                                                     image:[UIImage imageNamed:@"baseLineView_01"]];
    [self.view addSubview:baseLineView_01];
    
    
    [baseLineView_01 mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.centerY.equalTo(self.view);
        make.left.mas_equalTo(10);
    }];
    
    // BaselineLayoutView 02
    BaselineLayoutView *baseLineView_02 = [BaselineLayoutView baselineLayoutViewWithString:@"青春年少,任性而潇洒,像森林里一排不甘在下的幼林,倔强的生长,寻觅属于自己的广阔天空。"
                                                                                     image:[UIImage imageNamed:@"baseLineView_02"]];
    [self.view addSubview:baseLineView_02];
    
    [baseLineView_02 mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.baseline.equalTo(baseLineView_01.mas_baseline);
        make.right.mas_equalTo(-10.f);
    }];
}

@end
@interface BaselineLayoutView ()

@property (nonatomic, strong) NSString    *string;
@property (nonatomic, strong) UIImage     *image;

@property (nonatomic, strong) UILabel     *label;
@property (nonatomic, strong) UIImageView *imageView;

@end

@implementation BaselineLayoutView

+ (instancetype)baselineLayoutViewWithString:(NSString *)string image:(UIImage *)image {
    
    BaselineLayoutView *view = [[self class] new];
    view.string              = string;
    view.image               = image;
    [view initSubViews];
    
    return view;
}

- (void)initSubViews {
    
    self.backgroundColor = [UIColor lightGrayColor];
    
    // 图片
    self.imageView = [[UIImageView alloc] initWithImage:self.image];
    [self addSubview:self.imageView];
    
    [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.mas_equalTo(10);
        make.top.mas_equalTo(10);
        make.right.mas_equalTo(-10);
    }];
    
    // 以iamgeView的尺寸作为高优先级进行布局
    [self.imageView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [self.imageView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    
    // 文本
    self.label               = [UILabel new];
    self.label.numberOfLines = 0;
    self.label.font          = [UIFont systemFontOfSize:12.f];
    self.label.textColor     = [UIColor whiteColor];
    self.label.text          = self.string;
    [self addSubview:self.label];
    
    [self.label mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.mas_equalTo(10);
        make.top.mas_equalTo(self.imageView.mas_bottom).offset(10);
        make.right.mas_equalTo(-10);
        
        make.bottom.mas_equalTo(self.mas_bottom).offset(-10);
    }];
}

#pragma mark - Overwrite

- (UIView *)viewForLastBaselineLayout {
    
    return self.imageView;
}

@end

image.png

多样式cell

interface MultiStyleCell ()

@property (nonatomic, strong) UILabel *companyLabel;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *addressLabel;

@end

@implementation MultiStyleCell

- (void)setupCell {
    
    self.selectionStyle  = UITableViewCellSelectionStyleNone;
    
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.mas_equalTo(0).priorityHigh();
        make.top.mas_equalTo(0).priorityHigh();
        make.right.mas_equalTo(0).priorityHigh();
    }];
}

- (void)buildSubview {
    
    UIView *line         = [UIView new];
    line.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5f];
    [self.contentView addSubview:line];
    [line mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.mas_equalTo(0);
        make.bottom.mas_equalTo(0);
        make.right.mas_equalTo(0);
        make.height.mas_equalTo(0.5);
    }];
    
    self.companyLabel               = [UILabel new];
    self.companyLabel.numberOfLines = 0;
    self.companyLabel.font          = [UIFont systemFontOfSize:22];
    [self.contentView addSubview:self.companyLabel];
    
    self.nameLabel               = [UILabel new];
    self.nameLabel.numberOfLines = 0;
    self.nameLabel.font          = [UIFont systemFontOfSize:18];
    [self.contentView addSubview:self.nameLabel];

    self.addressLabel               = [UILabel new];
    self.addressLabel.numberOfLines = 0;
    self.addressLabel.font          = [UIFont systemFontOfSize:14.f];
    self.addressLabel.textColor     = [UIColor lightGrayColor];
    [self.contentView addSubview:self.addressLabel];
}

- (void)loadContent {
    
    self.companyLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 30.f;
    self.nameLabel.preferredMaxLayoutWidth    = [UIScreen mainScreen].bounds.size.width - 30.f;
    self.addressLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 30.f;
    
    MultiStyleModel *model      = self.data;
    UIView          *supperView = self.contentView;
    
    self.companyLabel.text = model.company;
    self.nameLabel.text    = model.userName;
    self.addressLabel.text = model.address;
    
    // companyLabel位置依赖于contentView,如果没有值,则紧贴着contentView的顶部
    [self.companyLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
        
        if (model.company.length > 0) {
            
            make.top.mas_equalTo(15.f);
            make.left.mas_equalTo(15.f);
            
        } else {
         
            make.top.mas_equalTo(0);
            make.left.mas_equalTo(0);
            make.height.mas_equalTo(0);
        }
        
        make.bottom.lessThanOrEqualTo(supperView).offset(-15.f);
    }];
    
    // nameLabel位置依赖于companyLabel,如果没有值,则紧贴着companyLabel的顶部
    [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
        
        if (model.userName.length > 0) {
            
            make.top.mas_equalTo(self.companyLabel.mas_bottom).offset(15.f);
            make.left.mas_equalTo(15.f);
            
        } else {
         
            make.top.mas_equalTo(self.companyLabel.mas_bottom).offset(0.f);
            make.left.mas_equalTo(0);
            make.height.mas_equalTo(0);
        }

        make.bottom.lessThanOrEqualTo(supperView).offset(-15.f);
    }];
    
    // addressLabel位置依赖于nameLabel,如果没有值,则紧贴着nameLabel的顶部
    [self.addressLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
        
        if (model.address.length > 0) {
            
            make.top.mas_equalTo(self.nameLabel.mas_bottom).offset(15.f);
            make.left.mas_equalTo(15.f);
            
        }  else {
            
            make.top.mas_equalTo(self.nameLabel.mas_bottom).offset(0.f);
            make.left.mas_equalTo(0);
            make.height.mas_equalTo(0);
        }
        
        make.bottom.lessThanOrEqualTo(supperView).offset(-15.f);
    }];
}

@end

image.png

项目来源:https://github.com/YouXianMing/AutoLayoutExample

上一篇下一篇

猜你喜欢

热点阅读