码迷,mamicode.com
首页 > 其他好文 > 详细

AutoLayout五、使用Masonry完成UITableViewCell的自适应高度

时间:2015-07-29 00:56:56      阅读:469      评论:0      收藏:0      [点我收藏+]

标签:

 第一步、Base TableViewController 封装tableView的 数据源方法、代理方法。这里只给出cell height的代理函数部分:

  

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    //不使用高度自适应的cell,返回其设置的默认高度
    if (![[self cellClass] isDynamic]) {
        return [self cellDefaultHeight];
    }
        
    __weak typeof(self) weakSelf = self;
    
    //每个Cell类设置的,默认Size
    CGSize defaultSize = [[self cellClass] defaultCellSize];
    
    //计算后自适应的 size
    CGSize cellSize = [[self cellClass] sizeForCellWithDefaultSize:defaultSize
                                                    setupCellBlock:^id(id<ZSYAutoLayoutCellProtocol> cellToSetup)
    {
        NSArray *dataList = [weakSelf dataSource];
        id obj = nil;
        
        //取出当前cell,要显示的实体对象
        if ([self sectionCount] == 1) {
            //dataSource是一维数组
            obj = dataList[[indexPath row]];
        } else {
            //dataSource是一维数组
            NSArray *sectionArray = dataList[indexPath.section];
            obj = sectionArray[indexPath.row];
        }

        //让cell根据实体对象【决定哪些view显示数据,显示什么数据,让cell针对当前实体对象的属性,初始化cell.contentView.subViews 】
        [cellToSetup setupDataItem:obj];
    
        //返回一个设置完了显示数据、设置好内部subViews约束的cell对象
        return cellToSetup;

    }];
    
    return cellSize.height;

}

 

第二步、BaseCell封装计算设置好约束、设置好显示数据cell对象高度的方法

+ (CGSize)sizeForCellWithDefaultSize:(CGSize)defaultSize setupCellBlock:(setupCellBlock)block {

    __block ZSYBaseCell *cell = nil;
    
    //使用一个静态变量数组cellArray保存所有需要适配高度的Cell类的一个唯一的对象,方便后续计算cell设置好数据后的高度    

    //先从静态数组查找,是否存在当前需要适配高度的cell类型的一个对象
    [cellArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[[self class] class]]) {
            cell = obj;
            *stop = YES;
        }
    }];
    
    //如果没找到,就创建一个新的cell对象,并保存到静态数组,方便后续使用
    if (!cell) {
        cell = [[[self class] alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"XZHAutoLayoutCellIdentifier"];
        cell.frame = CGRectMake(0, 0, defaultSize.width, defaultSize.height);
        [cellArray addObject:cell];
    }
    
    //针对一些cell不同数据,cell内部的subViews发生增加、减少类似的情况。通过子类cell重写这个方法,完成在不同的实体数据时,增加删除subviews
    [cell resetSubviews];

    //获取到设置了属性值的cell对象【会执行一次cell的setupData方法】
    cell = block((id<ZSYAutoLayoutCellProtocol>) cell);
    
    //最好写上
    [cell setNeedsLayout];
    [cell layoutIfNeeded];
    
    //使用系统函数,计算得到cell的高度
    //注意: 【必须在cell对象调用setupData: 时,对内部subviews正确设置约束,此时才能正确计算出高度】
    CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

    //加上一个1.0f,cell底部的分割线
    size.height += 1.0f;
     
    //返回高度
    return size;
}

 

第三步、编写继承自BaseCell的HomePageCell完成高度自适应

 

效果图:

技术分享

 

技术分享技术分享

cell结构:

一个imageview,一个label, 多张不固定的图片、每个图片可以有一个优惠的圆形label

 

// 第一步、cell在init初始化时,创建公共的subviews添加到contentView,并设置约束

- (id)initWithStyle:(UITableViewCellStyle)style
    reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self initSubviews];
    }
    return self;
}

- (void)initSubviews {
    _subViews = [NSMutableArray array];
    
    self.backgroundColor = [UIColor whiteColor];
    self.accessoryType = UITableViewCellAccessoryNone;
    self.accessoryView = nil;
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    
    _titleLeftImageView = [[UIImageView alloc] init];
    _titleLeftImageView.image = [UIImage imageNamed:@"icon_title"];
    _titleLeftImageView.translatesAutoresizingMaskIntoConstraints = NO;
    _titleLeftImageView.contentMode = UIViewContentModeScaleAspectFill;
    
    _titleLabel = [[UILabel alloc] init];
    _titleLabel.textAlignment = NSTextAlignmentLeft;
    _titleLabel.numberOfLines = 0;
    _titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
    _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _titleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
    _titleLabel.textColor = [UIColor hex:@"#514647"];
    
    [self.contentView addSubview:_titleLeftImageView];
    [self.contentView addSubview:_titleLabel];
    
    @weakify(self);
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        @strongify(self);
        make.edges.equalTo(self);
        make.width.equalTo(self);
    }];
    
    //一定要给自动换行计算高度的label,设置最大宽度
    [self preferMaxWidthLabels];
    
//    [self setNeedsUpdateConstraints];
//    [self updateConstraintsIfNeeded];
}

 

// 第二步、 给Label设置最大宽度
- (void)preferMaxWidthLabels {
    
    _metricDict = @{
                      @"sideBuffer1" : @12,
                      @"sideBuffer2" : @10,
                      @"vertical_top_Buffer" : @12,
                      @"vertical_middle_Buffer" : @16,
                      @"vertical_bottom_Buffer" : @12.5,
                      @"labelImageSizeWith" : @(_titleLeftImageView.image.size.width),
                      @"labelImageSizeHeight" : @(_titleLeftImageView.image.size.height),
                      @"contentImageSizeHeight" : @181
                      };
    
//    [self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
//    [self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
    
    
    CGSize defaultSize = [[self class] defaultCellSize];
    _titleLabel.preferredMaxLayoutWidth = defaultSize.width - [_metricDict[@"sideBuffer1"] floatValue] -[_metricDict[@"labelImageSizeWith"] integerValue] - 5 - [_metricDict[@"sideBuffer2"] integerValue];
}

 

// 第三步、tableview代理函数,返回当前显示cell的方法,取出当前cell即将显示的实体对象,然后调用cell对象的 设置数据方法

- (void)setupDataItem:(id)data {
    
    if ([data isKindOfClass:[ZSYEntityModule class]]) {
        _entity = (ZSYEntityModule *)data;
        _titleLabel.text = _entity.title;
        
        //对当前传入实体对象,增加或修改,cell.contentView.subviews
        [self customLayoutSubviews];
        
        //马上执行系统的 updateConstraints方法
        [self setNeedsUpdateConstraints];
        [self updateConstraintsIfNeeded];
    }
}

 

- (void)customLayoutSubviews {
    
    //取出当前要显示的图片张数,依次创建subview,并添加到cell.contentView
    for (NSString *url in _entity.hots) {
        
        __block UIImageView *subView = [[UIImageView alloc] init];
        [self.contentView addSubview:subView];
        
        UILabel *icon = [self newIcon];
        [subView addSubview:icon];
        
        [icon mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.mas_equalTo(subView.mas_top);
            make.right.mas_equalTo(subView.mas_right).offset(-5);
            make.size.mas_equalTo(CGSizeMake(Cordius*2 , Cordius*2));
        }];

        
        //测试设置图片
//        if ([url containsString:@"http"]) {
//            [subView sd_setImageWithURL:[NSURL URLWithString:url]
//                       placeholderImage:[UIImage imageNamed:@"blankpage_image_Hi"]
//                                options:SDWebImageProgressiveDownload];
//        } else {
            [subView setImage:[UIImage imageNamed:url]];
//        }
        
        _lastView = subView;
        [_subViews addObject:subView];
    }
}

 

// 最后就是重写系统方法,更新约束

- (void)updateConstraints {
    @weakify(self);
    
    CGFloat width = [_metricDict[@"labelImageSizeWith"] integerValue];
    CGFloat height= [_metricDict[@"labelImageSizeHeight"] integerValue];
    [_titleLeftImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        @strongify(self);
        make.top.mas_equalTo(self.contentView.mas_top).offset(14);
        make.left.mas_equalTo(self.contentView.mas_left).offset(12);
        make.size.mas_equalTo(CGSizeMake(width, height));
    }];
    
    [_titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        @strongify(self);
        make.top.mas_equalTo(self.contentView.mas_top).offset(12).priority(751);
        make.left.mas_equalTo(self.titleLeftImageView.mas_right).offset(5);
    }];
    
    __block UIImageView *last = nil;
    for (int i = 0; i < _subViews.count; i++) {
        UIImageView *subView = _subViews[i];
        
        [subView mas_makeConstraints:^(MASConstraintMaker *make) {
            @strongify(self);
            make.left.mas_equalTo(self.contentView.mas_left).offset(10);
            make.right.mas_equalTo(self.contentView.mas_right).offset(-10);
            if (last) {
                make.top.mas_equalTo(last.mas_bottom).offset(Cordius+2).priority(749);
            } else {
                make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(15).priority(749);
            }
            make.height.mas_equalTo(@180);
        }];
        
        last = subView;
    }
    
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.mas_equalTo(last.mas_bottom).offset(10);
    }];
    
    //一定要写
    [super updateConstraints];
}

 

AutoLayout五、使用Masonry完成UITableViewCell的自适应高度

标签:

原文地址:http://www.cnblogs.com/xiongzenghui/p/4684763.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!