今天研究了用Masonry库+UITableView(嵌套UICollectionView),实现高度动态自适应。
线上动态效果图如下:
----
主要代码:
1. 初始化并设置tableView
设置tableView.estimatedRowHeight = 100;//预估高度
tableView.rowHeight = UITableViewAutomaticDimension;//高度自适应
tableView.tableFooterView = [[UIView alloc] init];//底部不会多出空白。
2. 添加并约束tableView
[self.view addSubview:tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
if(@available(iOS11.0, *)) {// iOS11之后,适应SafeArea安全区域,masonry做的适配。如此设置 即可适配iPhoneX 刘海屏系列
make.left.equalTo(weakSelf.view.mas_safeAreaLayoutGuideLeft);
make.top.equalTo(weakSelf.view.mas_safeAreaLayoutGuideTop);
make.right.equalTo(weakSelf.view.mas_safeAreaLayoutGuideRight);
make.bottom.equalTo(weakSelf.view.mas_safeAreaLayoutGuideBottom);
}else{
make.edges.equalTo(weakSelf.view);
}
3. 造数据,实现tableView相关代理,构建tableViewCell 然后初始化cell中的CollectionView并进行约束
CGFloat wh = (kScreenWidth - 20)/3.0;
flowLayout.itemSize=CGSizeMake(wh, wh);//这里用固定的itemSize
flowLayout.minimumLineSpacing = 10;//行间距
flowLayout.minimumInteritemSpacing = 10;//列间距
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(weakSelf.contentView);//上左下右均约束到contentView的上左下右边缘。
make.height.mas_equalTo(wh).priority(100);//特别的是:这里需要加个height的约束,并优先级设置为低。 没加这条约束,初次显示时会不正常。因为初次显示此cell的内容如果没撑开contentView的话,就默认显示44高度。
}];
4. 传入数据到tableViewCell,点击collectionView中的最后一个item,新造一条数据,然后更新约束,适应高度变化。
- (void)setImgs:(NSMutableArray*)imgs{
_imgs= imgs;
[self.collectionView reloadData];
}
- (void)collectionView:(UICollectionView*)collectionView didSelectItemAtIndexPath:(NSIndexPath*)indexPath{
if(indexPath.item==self.imgs.count-1) {
//点击"+",追加一条数据
[self.imgs insertObject:[self.imgs firstObject] atIndex:0];
//刷新collectionView
[self.collectionView reloadData];//此处必须要reloadData,以用最新的数据源刷新并撑开collectionView的ContentSize。
CGFloat updateHeight = self.collectionView.collectionViewLayout.collectionViewContentSize.height;//这里就拿最新撑开的ContentSize去更新高度约束。
[self.collectionView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(updateHeight).priority(100);//这里必须要和前面的heigth约束语句一致。 否则会被masonry认为是新的一条约束,然后添加,导致Xcode输出控制台打印约束警告。
}];
//collectionView更新约束,回调通知tableView reload,然后撑开了tableViewCell的contentView进而撑开tableViewCell,实现高度自适应。
if (self.addBlock) {
self.addBlock();
}
}
}
5. 在addBlock回调里
cell.addBlock= ^() {
[weakSelf.tableView reloadData];
//为了避免抖动。
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
};
}];