iOS tableView cell高度自动布局 (masonry)

1.cell自动布局应用场景

对于一个cell有多种状态,涉及到显示或者隐藏某些view,并且cell高度随时改变,如果用viewmodel来计算的话,很复杂增加了很多代码量,而且如果状态考虑的不全极有可能造成错误,如果用自动布局的话,则没有这么多的顾及。

2.tableView设置

  • tableview的懒加载中设置这两个属性
  _tableView.estimatedRowHeight = 110*kWidthRatio;
  _tableView.rowHeight = UITableViewAutomaticDimension;

UITableViewAutomaticDimension 是float型返回的值恒为-1,意思是告诉tableview我的cell是自动布局的。这句代码等同于_tableView.rowHeight = -1;

  • 如果你的tableview中有多种cell有的cell布局不会改变,那么久可以用绝对布局,这时不要设置_tableView.rowHeight,而是在代理中实现
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    switch (indexPath.section) {
        case 0:{
            return UITableViewAutomaticDimension;
        }
            break;
        case 1:{
            return 110*kWidthRatio;
        }
            break;
            
        default:
            return 0;
            break;
    }

}

这里代码可以看出tableview中既有自动布局又有绝对布局

3.自定义Cell内的布局

+ (BOOL)requiresConstraintBasedLayout
{
    return YES;
}

- (void)updateConstraints{

    WEAKSELF
    //物流
        [self.wuLiuView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(0);
            make.top.mas_equalTo(0);
            make.width.mas_equalTo(ScreenW).priority(750);
            //切换物流信息展示状态, 同一个约束更改不同的状态设置不同的优先级以避免约束冲突
            if (weakSelf.wuLiuView.isHidden) {
                make.bottom.mas_equalTo(0).priority(500);
            }else{
                make.bottom.equalTo(self.dateLabel.mas_bottom).offset(15*kWidthRatio);
            }
        }];
        
        [self.wuliuStatusLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.busIcon.mas_right).offset(11*kWidthRatio);
            make.top.mas_equalTo(15*kWidthRatio);
            make.width.mas_equalTo(300*kWidthRatio);
            make.height.mas_lessThanOrEqualTo(40*kWidthRatio);
        }];
        
        [self.dateLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.wuliuStatusLabel);
            make.top.equalTo(self.wuliuStatusLabel.mas_bottom).offset(5*kWidthRatio);
            make.width.mas_greaterThanOrEqualTo(150*kWidthRatio);
            make.height.mas_equalTo(18*kWidthRatio);
        }];
        
        
        [self.rightArrow mas_makeConstraints:^(MASConstraintMaker *make) {
            make.width.mas_equalTo(7*kWidthRatio);
            make.height.mas_equalTo(12*kWidthRatio);
            make.right.equalTo(self.wuLiuView).offset(-15*kWidthRatio);
            make.centerY.equalTo(self.wuLiuView);
        }];
        
        [self.busIcon mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(14*kWidthRatio);
            make.centerY.mas_equalTo(self.wuLiuView);
            make.width.mas_equalTo(16*kWidthRatio);
            make.height.mas_equalTo(14*kWidthRatio);
        }];
        
        [self.sepView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(15*kWidthRatio);
            make.top.equalTo(self.wuLiuView.mas_bottom).offset(-0.5*kWidthRatio);
            make.width.mas_equalTo(ScreenW-30*kWidthRatio);
            make.height.mas_equalTo(0.5*kWidthRatio);
        }];

    //地址
    [self.addressView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self);
        make.top.equalTo(self.wuLiuView.mas_bottom);
        make.width.equalTo(self);
        make.height.mas_equalTo(75*kWidthRatio);
    }];
    
    [self.locateIcon mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(16*kWidthRatio);
        make.top.mas_equalTo(27*kWidthRatio);
        make.width.mas_equalTo(14*kWidthRatio);
        make.height.mas_equalTo(16*kWidthRatio);
    }];
    
    [self.nameAndTelLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.locateIcon.mas_right).offset(10*kWidthRatio);
        make.top.mas_equalTo(15*kWidthRatio);
        make.width.mas_equalTo(200*kWidthRatio);
        make.height.mas_equalTo(18*kWidthRatio);
    }];
    
    [self.addressLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.nameAndTelLabel);
        make.top.equalTo(self.nameAndTelLabel.mas_bottom).offset(5*kWidthRatio);
        make.width.mas_lessThanOrEqualTo(300*kWidthRatio);
        make.height.mas_greaterThanOrEqualTo(18*kWidthRatio);
    }];
    
    [self.colorLine mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(0);
        make.top.mas_equalTo(70*kWidthRatio);
        make.width.mas_equalTo(ScreenW);
        make.height.mas_equalTo(5*kWidthRatio);
    }];
    
    //重点
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.right.equalTo(self);
        make.bottom.equalTo(self.addressView);
    }];
    [super updateConstraints];
}

-(void)setViewModel:(GMOrderDetailViewModel *)viewModel{
    _viewModel = viewModel;
    self.wuLiuView.hidden = viewModel.isWuLiuViewHidden;  //会触发layoutsubviews
    self.wuliuStatusLabel.text = viewModel.deliverStatusDes;
    self.dateLabel.text = viewModel.deliverDate;
    self.nameAndTelLabel.text = [NSString stringWithFormat:@"%@ %@",viewModel.name,viewModel.telNumber];
    self.addressLabel.text = viewModel.address;

    //更新约束
    // tell constraints they need updating
    [self setNeedsUpdateConstraints];
    // update constraints now so we can animate the change
    [self updateConstraintsIfNeeded];
    
//    //未付款取消订单后展示物流信息,动态弹出效果
//    [UIView animateWithDuration:0.5 animations:^{
//        [self layoutIfNeeded];
//    }];
}

这里一个订单详情页的cell,有一个wuliuView在未付款时隐藏,在有的状态下只显示时间, 有的时候显示物流信息和时间,且高度字随机的,所以在设置完数据后要更新约束,
[self setNeedsUpdateConstraints];是通知约束他们即将更新
[self updateConstraintsIfNeeded]; 更新约束条件,并且可以使layoutIfNeeded带有动画效果。

4.解决约束冲突

我们可以看到wuLiuView在更新约束时对bottom在状态改变时更新了约束,那么问题来了,当一个属性约束条件更改时会有约束冲突,导致约束失效并报警高,我们调试的方法是,给报警高的约束设置优先级,这样就可以更改布局了, 掌握了布局的优先级就等于婉转了masonry,一般起冲突的布局都是因为我们在更改约束条件时没有添加它对应的优先级导致

你可能感兴趣的:(基础开发)