美文网首页
Masonry布局

Masonry布局

作者: Xl_Lee | 来源:发表于2021-03-01 20:57 被阅读0次

    设定上下左右内边距

    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

    相关文章

      网友评论

          本文标题:Masonry布局

          本文链接:https://www.haomeiwen.com/subject/qmkwfltx.html