Multiple collection views in table view layout issue

18 Views Asked by At

I have a single table view and it has a 4 sections. Every sections i registered a different collection view cells. In a table view cell, i'm having trouble setting the constraints of collection views to completely cover the table view section's row.

This is my tableView;

enum Sections: Int {
    case country = 0
    case categories = 1
    case popular = 2
    case specials = 3
}

private lazy var tableView: UITableView = {
        let tableView = UITableView(frame: .zero, style: .grouped)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.register(HomeVCTableViewCell.self, forCellReuseIdentifier: HomeVCTableViewCell.identifier)
        tableView.showsVerticalScrollIndicator = false
        tableView.separatorStyle = .none
        tableView.backgroundColor = UIColor.clear
        return tableView
    }()

and delegate, datasource;

extension HomeVC: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return sectionsTitles.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: HomeVCTableViewCell.identifier, for: indexPath) as? HomeVCTableViewCell else {
            return UITableViewCell()
        }
        
        switch indexPath.section {
        case Sections.country.rawValue:
            cell.configureCountryCell(with: areas)
        case Sections.categories.rawValue:
            return UITableViewCell()
        case Sections.popular.rawValue:
            return UITableViewCell()
        case Sections.specials.rawValue:
            return UITableViewCell()
        default:
            return UITableViewCell()
        }
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionsTitles[section]
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        switch indexPath.section {
        case Sections.country.rawValue:
            return 120
        case Sections.categories.rawValue:
            return 220
        case Sections.popular.rawValue:
            return 120
        case Sections.specials.rawValue:
            return 120
        default:
            return 120
        }
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 40
    }
    
    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        guard let header = view as? UITableViewHeaderFooterView else { return }
        header.textLabel?.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
        header.textLabel?.textColor = .black
    }
}

And custom tableViewCell;

class HomeVCTableViewCell: UITableViewCell {

    static let identifier = "HomeVCTableViewCell"
    
    private lazy var countryCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 120, height: 50)
        layout.scrollDirection = .horizontal
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.register(CountryCollectionViewCell.self, forCellWithReuseIdentifier: CountryCollectionViewCell.identifier)
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
        collectionView.showsHorizontalScrollIndicator = false
        return collectionView
    }()
    
    private lazy var categoriesCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 150, height: 200)
        layout.scrollDirection = .horizontal
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.register(CategoriesCollectionViewCell.self, forCellWithReuseIdentifier: CategoriesCollectionViewCell.identifier)
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
        collectionView.showsHorizontalScrollIndicator = false
        return collectionView
    }()
    
    private lazy var popularCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 150, height: 200)
        layout.scrollDirection = .horizontal
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.register(PopularCollectionViewCell.self, forCellWithReuseIdentifier: PopularCollectionViewCell.identifier)
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
        collectionView.showsHorizontalScrollIndicator = false
        return collectionView
    }()
    
    private lazy var specialsCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 150, height: 200)
        layout.scrollDirection = .horizontal
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.register(SpecialsCollectionViewCell.self, forCellWithReuseIdentifier: SpecialsCollectionViewCell.identifier)
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
        collectionView.showsHorizontalScrollIndicator = false
        return collectionView
    }()
    
    var areas = [String]()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        configureView()
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        countryCollectionView.frame = bounds
        
    }
    
    func configureCountryCell(with areas: [String]) {
        self.areas = areas
        
        DispatchQueue.main.async { [weak self] in
            self?.countryCollectionView.reloadData()
        }
    }
    
    private func configureView() {
        let collectionViews: [UICollectionView] = [countryCollectionView, categoriesCollectionView, popularCollectionView, specialsCollectionView]
        collectionViews.forEach { collectionView in
            collectionView.delegate = self
            collectionView.dataSource = self
            addSubview(collectionView)
        }
    }
}

extension HomeVCTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if collectionView == countryCollectionView {
            return areas.count
        } else if collectionView == categoriesCollectionView {
            return 1
        } else if collectionView == popularCollectionView {
            return 0
        } else if collectionView == specialsCollectionView {
            return 0
        } else {
            return 0
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if collectionView == self.countryCollectionView {
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CountryCollectionViewCell.identifier, for: indexPath) as? CountryCollectionViewCell else { return UICollectionViewCell() }
            
            cell.configure(with: areas[indexPath.row])
            return cell
        } else if collectionView == categoriesCollectionView {
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CategoriesCollectionViewCell.identifier, for: indexPath) as? CategoriesCollectionViewCell else { return UICollectionViewCell() }
            
            return cell
        } else if collectionView == popularCollectionView {
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PopularCollectionViewCell.identifier, for: indexPath) as? PopularCollectionViewCell else { return UICollectionViewCell() }
            
            return cell
        } else if collectionView == specialsCollectionView {
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SpecialsCollectionViewCell.identifier, for: indexPath) as? SpecialsCollectionViewCell else { return UICollectionViewCell() }
            
            return cell
        } else {
            return UICollectionViewCell()
        }
    }
    
    
}

When i set "countryCollectionView.frame = bounds" there is no issue and i can see categoriesCollectionView's items. But when i set all collection views like this:

override func layoutSubviews() {
        super.layoutSubviews()
        
        countryCollectionView.frame = bounds
        categoriesCollectionView.frame = bounds
        popularCollectionView.frame = bounds
        specialsCollectionView.frame = bounds
        
    }

I i can't see any of collection views items.

I tried

override func layoutSubviews() {
        super.layoutSubviews()
        
        countryCollectionView.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height)
        categoriesCollectionView.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height)
        popularCollectionView.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height)
        specialsCollectionView.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height)
        
    }

but nothing has changed.

0

There are 0 best solutions below