9

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
    }
}
Eitana Aviv
  • 103
  • 1
  • 4
  • 3
    Please, provide your code to show what have you did so far – Taras Chernyshenko Jul 31 '18 at 13:51
  • 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 Jul 31 '18 at 14:38
  • I've added my code with a screenshot, hoping this is well enough to understand my issue. Thanks!! – Eitana Aviv Aug 01 '18 at 07:25
  • 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 section – Mathi Arasan Aug 01 '18 at 07:38
  • 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 Aug 01 '18 at 10:34
  • this might help you https://stackoverflow.com/questions/57216791/self-sizing-tableview-inside-self-sizing-tableview-cell – えるまる Aug 26 '19 at 05:48
  • where are automatic dimensions for tableViewCell ? – Abu Ul Hassan Aug 29 '19 at 06:55

1 Answers1

5

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)
    
Learner
  • 1,107
  • 12
  • 14