5
votes

I'm developing an app which requires me to have two types of feed inside my ViewController - Horizontal and Vertical.

The structure is like this: ViewController -> UITableView -> first section has horizontal UICollectionView -> second section has vertical UICollectionView.

My issue is that i'm unable to get the second section of the UITableView (which has inside the Vertical UICollectionView) to have a proper height. It gets interrupted in the middle when I'm scrolling down.

It's important to say that the UICollectionView cell height is not fixed.

I followed some tutorials and guides out there and saw many use cases of UITableViewAutomaticDimension, but couldn't get it to work.

Edit: Here is how my storyboard looks like: My StoryBoard This is my main ViewController code:

class FeedViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!

    var stationArray = Array()

    override func viewDidLoad() {
        super.viewDidLoad()d
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 2
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return categories[section]
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! FeedHorizontalTableViewCell
            *Some code*
            return cell
        } else {
            let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2") as! FeedVerticalTableViewCell
            *Some code*
            cell2.setNeedsLayout()
            return cell2
        }
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        if section == 1 {
            return 50
        }

        return 0
    }

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 500
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            if indexPath.section == 0 {
                if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") {
                    return cell.frame.height
                }
                return 280
            } else {
                return UITableViewAutomaticDimension
            }
    }
}

This is my vertical UITableViewCell code:

class FeedVerticalTableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    @IBOutlet weak var collectionView: UICollectionView!

    var stations = Array() {
        didSet {
            collectionView.reloadData()
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return stations.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "feedVerticalCell", for: indexPath) as! FeedVerticalCollectionViewCell
        *some code*
        return cell
    }
}
1
Please, provide your code to show what have you did so farTaras Chernyshenko
I think You must calculate CollectionView height buy code and pass it to tableView delegate in: func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { <#code#> } (and use a custom algorithm when rotating..) anyway without a sample code is a bit strange. pls forget "automatic": for custom interfaces all must be conde by coders in code :(ingconti
I've added my code with a screenshot, hoping this is well enough to understand my issue. Thanks!!Eitana Aviv
From your question what I understand mean: That UI needs to scroll vertically (horizontal scroll also scroll with that). If you want like that put your UITableView as group type and set the horizontal scroll in section header. Just use only one sectionMathi Arasan
Thanks for your reply @MathiArasan, but the issue is with the collectionview height of the vertical tableview cell (the second cell) which is not correct.Eitana Aviv

1 Answers

5
votes

After setting UITableView cell height to be dynamic in you view controller.

     tableView.estimatedRowHeight = 100
     tableView.rowHeight = UITableViewAutomaticDimension
  1. Create a subclass for your vertical 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
       }
    }
    
  2. In Interface builder change the class of your collectionView to DynamicCollectionView (subclass UICollectionView).

  3. Set estimated cell size of UICollectionViewFlowLayout.

        flowLayout.estimatedItemSize = CGSize(width: 1,height: 1)