So let me start by explaining the view hierarchy.
I'm using a normal UITableView, inside the UITableViewCell there is a collectionView which is dynamic in height.
How I'm setting the datasource and delegate for UICollectionView at the willDisplay cell of UITableView:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if indexPath.section == 0 {
guard let collectionCell = cell as? movieListingTableViewCell else { return }
collectionCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
collectionCell.selectionStyle = .none
}
}
The collectionView has the top, bottom, leading, trailing and height constraints.
Then I'm using the height constraint and setting it to the collectionView height as so in the UITableView cell subclass,
override func layoutSubviews() {
timingCollectionHeight.constant = timingCollection.collectionViewLayout.collectionViewContentSize.height
}
What happens is that my cells are not appearing properly as in there are blank spaces. For eg, if there is one UITableView cell which has a collectionView with a large height, other UITableView cells also somehow use the same height. After scrolling through the table the cells appear correctly.
Swift Example
First, get an outlet of your collectionViewHeightConstraint in your tableViewCell Class as shown below:-
@IBOutlet weak var collectionViewHeight: NSLayoutConstraint!
Then inside viewDidLoad() method of your ViewController Class add below code for dynamic height of tableViewCell:-
myTableView.estimatedRowHeight = 100; // Default tableViewCell height
myTableView.rowHeight = UITableViewAutomaticDimension;
Then inside your tableView cellForRowAtindexPath delegate add below code to update the height of tableView Cell as per CollectionView height:-
cell.frame = tableView.bounds; // cell of myTableView
cell.layoutIfNeeded()
cell.myCollectionView.reloadData()
cell.collectionViewHeight.constant = cell.myCollectionView.collectionViewLayout.collectionViewContentSize.height;
Hope this helps.
Happy Coding :)
Another approach:
After setting UITableView cell height to be dynamic.
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
Create a subclass for collectionView and override intrinsicContentSize.
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return collectionViewLayout.collectionViewContentSize
}
}
In Interface builder change the class of your collectionView to DynamicCollectionView (subclass UICollectionView).
Set estimated cell size of UICollectionViewFlowLayout.
flowLayout.estimatedItemSize = CGSize(width: 1,height: 1)