Custom Layout
Sometimes we have taken the multiple UICollectionView in a different cell of UITableView and each cell has a different size so for managing this thing we use autoresizing in UItableview.
for this we need to follow some steps:
1: We have to take UITableView and create their outlet like:
1 |
@IBOutlet weak var tableView: UITableView! |
Now define in Viewdidload method:
1 2 3 |
tableView.rowHeight = UITableViewAutomaticDimension self.tableView.estimatedRowHeight = 200 tableView.reloadData() |
2: Now register the UICollectionView and their properties in before reload call.
3: Now define the UITableViewCell class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class TableViewCell: UITableViewCell { @IBOutlet weak var collectionView: UICollectionView! override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize { // With autolayout enabled on collection view's cells we need to force a collection view relayout with the shown size (width) print("this" , collectionView?.collectionViewLayout.collectionViewContentSize) collectionView?.frame = CGRect(x: 0, y: 0, width: targetSize.width, height: 70) collectionView?.layoutIfNeeded() return (collectionView?.collectionViewLayout.collectionViewContentSize)! } } |
Note: This function manage the autoresizing of UICollectionView.
Now Define the delegate of UICollectionView:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
extension TableViewCell { func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & UICollectionViewDelegate>(_ dataSourceDelegate: D, forRow row: Int) { collectionView.delegate = dataSourceDelegate collectionView.dataSource = dataSourceDelegate collectionView.setContentOffset(collectionView.contentOffset, animated:false) // Stops collection view if it was scrolling. collectionView.reloadData() } var collectionViewOffset: CGFloat { set { collectionView.contentOffset.x = newValue } get { return collectionView.contentOffset.x } } } |
In ViewdidLoad class where you have taken outlet of UITableView :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 7 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) cell.backgroundColor = UIColor.red print("calling") return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { print("Collection view at row \(collectionView.tag) selected index path \(indexPath)") } } extension ViewController:UICollectionViewDelegateFlowLayout{ func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.size.width / 2 - 20, height:200) } func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } } |
1 2 3 4 5 6 7 8 9 |
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let CellIdentifier: String = "cell" print("table view"); var cell:TableViewCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as! TableViewCell cell.collectionView.tag = (100 * indexPath.section) + 1 cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.section) cell.collectionViewOffset = storedOffsets[indexPath.section] ?? 0 return cell; } |
Now you need to set the some delegate function to run the tableview .
and whatever the value passed in UICollectionview layout ,UItableview will automatic maintain their height .