ios中UITableView镶嵌UICollectionView正确设置高度及同时滑动

在tableview中嵌入collectionview时,如果没有正确设置高度,会产生collectionview不能全部展现,只能在内部滑动的现象,这与预期是不符的。

解决思路:在内嵌的collectionView进行布局的时候,拿到contentSize的高度h,然后在更新tableView cell的高度等于h.

两种方案

  1. 不使用tableView自适应行高
  2. 使用AutoLayout配合tableView的自适应行高

1. 不使用tableView的自适应行高

思路

  • 在tableView cellForRow阶段对cell中的collectionView reloadData,然后调用layoutIfNeeded()获取到的contentSize,并记录下这个高度h
  • cellForRowAt时,返回这个h就可以了.

需要注意

  • 不要在cellForRowAt中通过tableView获取cell,然后拿cell的高度,其实你拿也拿不到,因为这个时候cell还没有显示出来,tableView.cellForRow(at: indexPath)拿到的是nil,另外collectionView reloadData后,需要layoutIfNeeded才能正确拿到contentSize,因为reloadData不是同步的,没办法同步拿到布局.

关键代码

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
	…
	cell.collectionView.data = someData
	cell.collectionView.reloadData()
	cell.collectionView.layoutIfNeeded()
	collectionCellHeight = cell.collectionvView.contentSize.height
	…
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
	…
	//if indexPath.row == collectionview所在cell的row
	return collectionCellHeight
	…
}

2. 使用tableView的自适应行高

思路

  • 首先启用tableView的自动行高(ios 7还是8以后默认是启用的)
  • 放置一个container在tableView cell的contentView上,collectionView放在container上;contentView的高度动态随container变化,container高度随collectionView变化
  • 当collection reload后立即layoutIfNeeded获取contentSize,然后更新container的高度,由于是自动高度,因此tableView的cell也会调整到container的高度
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44 // 设置一个和你的collectionView接近的值吧,默认44
class CustomCell: UITableViewCell {
    
    var dataArray: [String] = [] // 假定我们的数据结构就是一个String数组
    
    var collectionView: UICollectionView!
    
    var collectionContainer: UIView!
    
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        
        collectionContainer = UIView(frame: .zero)
        contentView.addSubview(collectionContainer)
        
        collectionContainer.mas_makeConstraints {
            $0?.left.equalTo()(self.contentView)
            // 这里需要指定宽度,因为collectionView布局的时候,tableView的cell的frame还没有正确设置还是estimate
            // 所以不可以这样!
            // $0?.left.and()?.right()?.equalTo()(self.contentView)
            $0?.width.equalTo()(UIScreen.main.bounds.width)
            $0?.top.and()?.bottom()?.equalTo()(self.contentView) // container的上下边和contentView一致,contentView会根据它的大小调整
            $0?.height.equalTo()(44) // 默认先随便一个值吧,最好接近真实值,后面会update到真实值
        }
        
        let layout = UICollectionViewFlowLayout()
        layout.minimumLineSpacing = 10
        layout.minimumInteritemSpacing = 10
        layout.itemSize = CGSize(width: 50, height: 50)
        layout.scrollDirection = .vertical
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionContainer.addSubview(collectionView)
        
        collectionView.mas_makeConstraints {
            $0?.edges.equalTo()(self.collectionContainer)
        }
        
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "test")

        collectionView.delegate = self // 这里根据具体业务写吧,demo中我就把代理直接设置成cell了..
        collectionView.dataSource = self // 根据业务,demo直接先cell持有数据来控制collectionView的显示了..
    }
    
    // 外部调用,用来设置collectionView的数据源
    func setData(_ data: [String]) {
        self.dataArray = data
        collectionView.reloadData()
        // 这里需要 layoutIfNeeded 一下,否则我们不能同步拿到contentSize
        // 注意,如果上面collectionContainer的布局没有指明宽度,这个时候cell的宽度是estimate状态,所以下面就算layout也拿不到正确的contentSize
        collectionView.layoutIfNeeded()

        let height = collectionView.contentSize.height
        
        collectionContainer.mas_updateConstraints { // 更新container的高度
            $0?.height.equalTo()(height)
        }
    }

}

需要注意

  • container需要指定宽度,否则拿到的是估算值,这个时候collectionView是他的子view,就算layoutIfNeeded也是以估算值来的,所以不不准确.

ps.

推荐一个自己写的app:本人喜欢玩暴雪的游戏,最近写了一个暗黑破坏神3的游戏工具,在里面做了一些UI性能、流畅性的优化,感兴趣的同学可以下载体验下,顺便给个评分~

ios中UITableView镶嵌UICollectionView正确设置高度及同时滑动_第1张图片

ios中UITableView镶嵌UICollectionView正确设置高度及同时滑动_第2张图片

 

你可能感兴趣的:(Swift,IOS)