UITableView高度自适应

3,677 阅读2分钟

1.UITableViewCell高度自适应

实现原理:

Cell高度自适应的原理是通过为contentView上的子view设置适当的约束,让Cell根据内容自动撑开.

实现步骤:

  • 创建UITableView并为estimatedRowHeight属性任意设置一个值.
  • 创建自定义Cell并为子控件设置合适的约束.
- (UITableView *)tableView {
    if (!_tableView) {
        ...
        // 任意给定一个高度 
        _tableView.estimatedRowHeight = 10;
        ...
        [_tableView registerClass:DynamicHeightFittingTableViewCell.class forCellReuseIdentifier:NSStringFromClass(DynamicHeightFittingTableViewCell.class)];
    }
    return _tableView;
}

@implementation DynamicHeightFittingTableViewCell

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

- (void)initUI {
    [self.contentView addSubview:self.titleLabel];
    [self.contentView addSubview:self.colorView];
    
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(10);
        make.left.mas_equalTo(10);
        make.right.mas_equalTo(-10);
    }];
    [self.colorView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(10);
        make.centerX.mas_equalTo(0);
        make.size.mas_equalTo(CGSizeMake(50, 50));
        make.bottom.mas_equalTo(-10);
    }];
}

@end

根据内容撑开思想可以计算出Cell的高度 = titleLabel_top + titleLabel高度(根据text计算得到) + colorView_top + colorView高度(通过约束指定size).

效果图:

UITableViewCell高度自适应

2.UITableView高度自适应

实现原理:

通过KVO监听UITableView的contentSize,当发生改变时立即更新tableView的高度约束.

实现步骤:

  • 创建UITableView并设置top、left、right约束.
  • KVO监听contentSize的变化.
  • 在KVO回调方法中对tableView进行约束的更新.
- (void)viewDidLoad {
    [super viewDidLoad];
		[self.view addSubview:self.tableView];
    [self.view addSubview:self.titleLabel];
    
    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(Status_And_Navigation_Height());
        make.left.right.mas_equalTo(0);
    }];
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.tableView.mas_bottom).mas_offset(10);
        make.left.mas_equalTo(10);
        make.right.mas_equalTo(-10);
        make.centerX.mas_equalTo(0);
    }];
    [self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:(__bridge void *)self.tableView];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (context == (__bridge void *)self.tableView) {
        if ([keyPath isEqualToString:@"contentSize"]) {
            [self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.top.mas_equalTo(Status_And_Navigation_Height());
                make.left.right.mas_equalTo(0);
                make.height.mas_equalTo(self.tableView.contentSize.height);
            }];
        }
    }
}

效果图:

UITableView高度自适应

3.UITableViewCell嵌套UICollectionView(自适应高度)

实现原理:

动态计算出UITableViewCell的高度.

实现步骤:

自定义UITableViewCell重写systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:方法或者systemLayoutSizeFittingSize:方法.

- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority {
    CGSize size = [super systemLayoutSizeFittingSize:targetSize withHorizontalFittingPriority:horizontalFittingPriority verticalFittingPriority:verticalFittingPriority];
    // 提前布局collectionView以便能获取到size
    [self.collectionView layoutIfNeeded];
    CGSize collectionViewContentSize = self.collectionView.collectionViewLayout.collectionViewContentSize;
    return CGSizeMake(size.width, size.height + collectionViewContentSize.height);
}

效果图:

UITableViewCell嵌套UICollectionView(自适应高度)

4.UITableViewCell嵌套UITableView(自适应高度)

实现原理:

动态计算出UITableViewCell的高度.

实现步骤:

  • 自定义UITableViewCell重写systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:方法或者systemLayoutSizeFittingSize:方法.
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority {
    CGSize size = [super systemLayoutSizeFittingSize:targetSize withHorizontalFittingPriority:horizontalFittingPriority verticalFittingPriority:verticalFittingPriority];
    // 提前布局collectionView以便能获取到size
    [self.tableView layoutIfNeeded];
    CGSize tableContentSize = self.tableView.contentSize;
    return CGSizeMake(targetSize.width, size.height + tableContentSize.height);
}
- (UITableView *)tableView { 
    if (!_tableView) { 
    ... 
    // 必须指定高度 不然有问题 暂时不知道什么原因 
    _tableView.rowHeight = 40; 
    ... 
    } 
    return _tableView; 
}
  • 需要指定嵌套UITableView的cell高度,不然tableView的高度计算会有问题.(原因暂时没时间研究,如果你知道可以交流交流~)

效果图:

UITableViewCell嵌套UITableView(自适应高度)

项目地址

github:github.com/CharonYH/YH…

如果你觉得本项目对你开发有帮助,辛苦给个star~