fl0_9
fl0_9

Reputation: 271

Collectionview in collectionview cell fitting to content

I have a collectionview with two sections, each sections have one item. The cell in section contains collectionview and I need to fit height cell to content collectionview.

My first section has a fixed height to 120 because it's horizontal collectionview and height not changed. But for second section number of elements can be changed and I need to display all items (collectionview have scrollEnabled to false and scrolldirecton to vertical).

My problem is I need to display a collectionview with two scrolldirection depends sections and display all items for vertical collectionview.

When I do collectionview.collectionViewLayout.collectionViewContentSize.height I have the good height but I don't know how passed this height to parent viewcontroller. I search a dynamic solution to fixed this.

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    // MARK: - UICollectionViewDataSource

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return presenter.numberOfSections // == 2
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return presenter.numberOfItemsInSection // == 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueCell(InlineDisplayCollectionViewCell.self, for: indexPath)
        configureCell(cell, at: indexPath)

        return cell
    }

    // MARK: - UICollectionViewDelegateFlowLayout

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let type = presenter.typeAtIndexPath(indexPath)
        switch type {
        case .city:
            return CGSize(width: collectionView.frame.width, height: 120)
        case .suggestion:
            return CGSize(width: collectionView.frame.width, height: 820)
        default:
            return CGSize.zero
        }
    }


}


class InlineDisplayCollectionViewCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    @IBOutlet weak var collectionView: UICollectionView!

    var itemType: ItemModelCollectionType! = .city {
        didSet {
            updateCell()
        }
    }
    var cities: [City]? {
        didSet {
            collectionView.reloadData()
        }
    }
    var suggestions: [Suggestion]? {
        didSet {
            collectionView.reloadData()
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()

        configureView()
    }

    // MARK: - UICollectionViewDataSource

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return itemType == .city ? cities?.count ?? 0 : suggestions?.count ?? 0
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell: UICollectionViewCell
        if itemType == .city {
            let cityCell = collectionView.dequeueCell(CityCollectionViewCell.self, for: indexPath)
            configure(cell: cityCell, at: indexPath)
            cell = cityCell
        } else {
            let suggestionCell = collectionView.dequeueCell(SquareCollectionViewCell.self, for: indexPath)
            configure(cell: suggestionCell, at: indexPath)
            cell = suggestionCell
        }
        return cell
    }

    // MARK: - UICollectionViewDelegateFlowLayout

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return itemType == .city ? 10 : 10
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return itemType == .city ? 0 : 10
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let size: CGSize
        if itemType == .city {
            size = CGSize(width: 100, height: 120)
        } else {
            let width = (collectionView.frame.width - (collectionView.contentInset.left + collectionView.contentInset.right) - 10) * 0.5
            let height = width
            size = CGSize(width: width, height: height)
        }

        return size
    }

    // MARK: - Private functions

    private func configureView() {
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
        collectionView.registerNib(CityCollectionViewCell.self, bundle: nil)
        collectionView.registerNib(SquareCollectionViewCell.self, bundle: nil)
    }

    private func updateCell() {
        if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.scrollDirection = itemType == .city ? .horizontal : .vertical
        }
        collectionView.isScrollEnabled = itemType == .city
    }

    private func configure(cell: CityCollectionViewCell, at indexPath: IndexPath) {
        guard let city = cities?[indexPath.row] else { return }
        cell.configure(with: city)
    }

    private func configure(cell: SquareCollectionViewCell, at indexPath: IndexPath) {
        guard let suggestion = suggestions?[indexPath.row] else { return }
        cell.configure(with: suggestion)
    }

}

Upvotes: 1

Views: 533

Answers (2)

Milosh Milivojevich
Milosh Milivojevich

Reputation: 19

Unfortunately you can't do something like that. But you can have different types of cells inside your CV. Also you can modify that in the function called "cellForItemAt".

Upvotes: 0

ISS
ISS

Reputation: 416

You can't do that. CollectionView cells are dequeued and reused dynamically. The best way to go about it is to use different types of cells within the same CollectionView.

Please check the questions I have posted on this topic: Get the sum of all collectionViewCells' heights inside a CollectionView and Multiple Cells for Comments and Reply in a CollectionView

Upvotes: 0

Related Questions