AutoLayout2、AutoLayout Cell 思路

 

整体思路:

  • 保存一个设置好约束的指定Cell类的对象     
  • 给Cell类对象填充须要显示的全部数据项(UILabel值、UIImageView图片...)
  • 而后在返回cell高度的回调函数中
  • 使用 [cell对象.cententView systemLayoutSizeFittingSize:UILayoutFitttingCompressSize] 让ios sdk替咱们计算cell的真实高度。

 

第一步、定义全部cell必须实现的对象方法--》将传入的实体对象设置给cell.contentView.subViews

#import <Foundation/Foundation.h>

@protocol ZSYAutoLayoutCellProtocol;

static CGFloat ZSYDynamicTableViewCellAccessoryWidth = 33;

//这个数组用来保存全部类型的自动布局的Cell类的一个对象,用于后面计算cell高度
static NSMutableArray *cellArray;

//先传出保存的cell对象,而后再用调用者返回设置了全部显示数据的cell对象,用于计算cell高度须要
typedef id (^setupCellBlock)(id<ZSYAutoLayoutCellProtocol> cellToSetup);

@protocol ZSYAutoLayoutCellProtocol <NSObject>

//全部cell设置数据
- (void)setupDataItem:(id)data;

//计算cell高度
+ (CGSize)sizeForCellWithDefaultSize:(CGSize)defaultSize setupCellBlock:(setupCellBlock)block;

@end

 

第二步、写一个BaseCell作一个默认实现接口

- (void)setupDataItem:(id)data {
    //这个方法子类cell重写,将实体对象设置给cell.contentView.subviews
}

+ (CGSize)sizeForCellWithDefaultSize:(CGSize)defaultSize setupCellBlock:(setupCellBlock)block {
    __block UITableViewCell *cell = nil;
    
    //查看静态数组内是否已经存在当前Cell类的一个对象
    [cellArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[[self class] class]]) {
            cell = obj;
            *stop = YES;
        }
    }];
    
    //若是不存在,建立一个当前Cell类型的对象,并保存到数组。后续计算当前Cell类型对象的高度时,直接使用这个保存的Cell对象
    if (!cell) {
        cell = [[[self class] alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"XZHAutoLayoutCellIdentifier"];
        cell.frame = CGRectMake(0, 0, defaultSize.width, defaultSize.height);
        [cellArray addObject:cell];

    }
    
    //获取到设置了属性值的cell对象[1.先回传出去 2.再接收Block的一个返回值cell对象]
    cell = block((id<ZSYAutoLayoutCellProtocol>) cell);
    
    //获取到cell对象的 CGSize
//    [cell.contentView layoutIfNeeded];
    CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    
    size.width = MAX(defaultSize.width, size.width);
    size.height = size.height + 1.0f;
    
    return size;
}

 

第三步、编写某个具体的Cell

// 实现接口定义的设置实体类对象的方法

- (void)setupDataItem:(id)data {
    if ([data isKindOfClass:[ZSYEntityModule class]]) {
        _entity = (ZSYEntityModule *)data;
        
        _titleLabel.text = _entity.title;
        [_contentImageView sd_setImageWithURL:[NSURL URLWithString:_entity.imageURL]
                             placeholderImage:[UIImage imageNamed:@"blankpage_image_Hi"]
                                      options:SDWebImageProgressiveDownload];
        
        //UILabel写上这一句
        [_titleLabel layoutIfNeeded];
    }
}

 

//给Cell.contentView.subviews分别设置约束,使用VFL

- (void)initSubviews {
    
    self.backgroundColor = [UIColor whiteColor];
    self.accessoryType = UITableViewCellAccessoryNone;
    self.accessoryView = nil;
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    [self.contentView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
    
    _titleLeftImageView = [[UIImageView alloc] init];
    _titleLeftImageView.image = [UIImage imageNamed:@"icon_title"];
    _titleLeftImageView.translatesAutoresizingMaskIntoConstraints = NO;
    _titleLeftImageView.contentMode = UIViewContentModeScaleAspectFill;
    
    _titleLabel = [[UILabel alloc] init];
    _titleLabel.numberOfLines = 0;
    _titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
    _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:15];
    _titleLabel.textColor = [UIColor hex:@"#514647"];
    
    _contentImageView = [[UIImageView alloc] init];
    _contentImageView.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.contentView addSubview:_titleLeftImageView];
    [self.contentView addSubview:_titleLabel];
    [self.contentView addSubview:_contentImageView];
    
    NSDictionary *viewDict = NSDictionaryOfVariableBindings(_titleLeftImageView, _titleLabel, _contentImageView);
    
    NSDictionary *metricDict = @{@"sideBuffer1" : @16,
                                 @"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};
    
    NSString *vfl = @"H:|-sideBuffer1-[_titleLeftImageView(labelImageSizeWith)]-5-[_titleLabel]-sideBuffer2-|";
    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl options:0 metrics:metricDict views:viewDict]];
    
    vfl = @"H:|-sideBuffer2-[_contentImageView]-sideBuffer2-|";
    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl options:0 metrics:metricDict views:viewDict]];
 
    vfl = @"V:|-vertical_top_Buffer-[_titleLeftImageView]";
    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl options:0 metrics:metricDict views:viewDict]];
    
    vfl = @"V:|-vertical_top_Buffer-[_titleLabel]-vertical_middle_Buffer-[_contentImageView(contentImageSizeHeight)]-vertical_bottom_Buffer-|";
    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl options:0 metrics:metricDict views:viewDict]];
    
//    vfl = @"V:[_contentImageView(contentImageSizeHeight)]-vertical_bottom_Buffer-|";
//    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vfl options:0 metrics:metricDict views:viewDict]];
    
//    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.titleLeftImageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.titleLabel attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
    
    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.titleLeftImageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.titleLabel attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    
//    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.titleLeftImageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.titleLabel attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];
    
    [self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
    
    //获取每一个cell重写后,本身的默认size
    CGSize defaultSize = [[self class] defaultCellSize];

    //注意: 全部UILabel若是须要高度动态改变,必定要设置preferredMaxLayoutWidth最大宽度
    self.titleLabel.preferredMaxLayoutWidth = defaultSize.width - [metricDict[@"sideBuffer1"] floatValue] -[metricDict[@"labelImageSizeWith"] integerValue] - 5 - [metricDict[@"sideBuffer2"] integerValue];

}

 

第四步、tableview回调代理函数cell高度

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    if (![[self cellClass] isDynamic]) {
        return [self cellDefaultHeight];
    }
        
    __weak typeof(self) weakSelf = self;
    
    //默认 size
    CGSize defaultSize = [[self cellClass] defaultCellSize];
    
    //计算后自适应的 size
    CGSize cellSize = [[self cellClass] sizeForCellWithDefaultSize:defaultSize
                                                    setupCellBlock:^id(id<ZSYAutoLayoutCellProtocol> cellToSetup)
    {
        NSArray *dataList = [weakSelf dataSource];
        if ([self sectionCount] == 1) {//一维数组
            [cellToSetup setupDataItem:dataList[[indexPath row]]];
        } else {//二惟数组
            NSArray *sectionArray = dataList[indexPath.section];
            id obj = sectionArray[indexPath.row];
            [cellToSetup setupDataItem:obj];
        }
        return cellToSetup;
    }];
    
    return cellSize.height;

}
相关文章
相关标签/搜索