UICollectionView inside a UITableViewCell — dynami

2019-01-03 11:42发布

One of our application screens requires us to place a UICollectionView inside of a UITableViewCell. This UICollectionView will have a dynamic number of items, resulting in a height which must be calculated dynamically as well. However, I am running into problems trying to calculate the height of the embedded UICollectionView.

Our overarching UIViewController was created in Storyboards and does make use of auto layout. But, I don't know how to dynamically increase the height of the UITableViewCell based on the height of the UICollectionView.

Can anyone give some tips or advice on how to accomplish this?

14条回答
Root(大扎)
2楼-- · 2019-01-03 12:28

I read through all the answers. This seems to serve all cases.

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()
        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width , height: 1)
        return collectionView.collectionViewLayout.collectionViewContentSize
}
查看更多
爷、活的狠高调
3楼-- · 2019-01-03 12:34

An alternative to Pablo Romeu's solution is to customise UICollectionView itself, rather than doing the work in table view cell.

The underlying problem is that by default a collection view has no intrinsic size and so cannot inform auto layout of the dimensions to use. You can remedy that by creating a custom subclass which does return a useful intrinsic size.

Create a subclass of UICollectionView and override the following methods

override func intrinsicContentSize() -> CGSize {
    self.layoutIfNeeded()

    var size = super.contentSize
    if size.width == 0 || size.height == 0 {
        // return a default size
        size = CGSize(width: 600, height:44)
    }

    return size
 }

override func reloadData() {
    super.reloadData()
    self.layoutIfNeeded()
    self.invalidateIntrinsicContentSize()
}

(You should also override the related methods: reloadSections, reloadItemsAtIndexPaths in a similar way to reloadData())

Calling layoutIfNeeded forces the collection view to recalculate the content size which can then be used as the new intrinsic size.

Also, you need to explicitly handle changes to the view size (e.g. on device rotation) in the table view controller

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
}
查看更多
登录 后发表回答