Add UICollectionView in UICollectionViewCell

前端 未结 4 1036
轻奢々
轻奢々 2020-12-29 16:47

I am using Swift to build an iOS application for the Hospital I work at.

Somehow, in a specific feature I have to put a UICollectionView inside the

相关标签:
4条回答
  • 2020-12-29 17:14

    Add collectionView in collection view cell , and add delagate methods in collectionviewclass.swift. Then pass list you want to show in cell in collectionview's cellforrowatindexpath. If you didn't success on implimenting it then let me know . i will provide you code as i have already implemented it in that way.

    0 讨论(0)
  • 2020-12-29 17:22

    This might be a little late, but for people out here still trying to find an answer.

    After some research and digging, I stumbled upon several posts stating reasons why you should NOT have your cell be the delegate for you collectionView. So, I was lost because pretty much all solutions I had found were doing this, until I finally found what I believe is the best way to have nested collectionViews.

    To give some background, my app included not only one but 2 collectionViews inside different cells of another collectionView, so setting the delegates with tags and all that, wasn't really the best approach nor the correct OO solution.

    So the best way to do it is the following:

    First you have to created a different class to serve as your delegate for the inner collectionView. I did it as such:

    class InnerCollectionViewDelegate: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
     // CollectionView and layout delegate methods here
     // sizeForItemAt, cellForItemAt, etc...
    }
    

    Now, in your inner collectionView (or rather the cell where you have the inner collectionView) create a function that will allow you to set its delegates

    class InnerCell: UICollectionViewCell {
    
        var collectionView: UICollectionView
    
        init() {
            let layout = UICollectionViewFlowLayout()
            collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height), collectionViewLayout: layout)
         }
    
        func setCollectionViewDataSourceDelegate(dataSourceDelegate: UICollectionViewDataSource & UICollectionViewDelegate) {
                collectionView.delegate = dataSourceDelegate
                collectionView.dataSource = dataSourceDelegate
                collectionView.reloadData()
        }
    }
    

    And lastly, in your ViewController where you have your outermost (main) collectionView do the following:

    First instantiate the delegate for the inner collectionView

    var innerDelegate = InnerCollectionViewDelegate()
    

    and then

    override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
            if let cell = cell as? InnerCell {
                cell.setCollectionViewDataSourceDelegate(dataSourceDelegate: innerDelegate)
            }
    }
    

    This might not be perfect, but at least you have separation of concerns, as your cell should NOT be the delegate. Remember your cell should only be responsible for displaying info, not trying to figure out what the size of the collectionView should be, etc.

    I did find similar answers that dealt with setting the collectionViews tag and whatnot, but I found that that made it way harder to deal with each collectionView individually, plus dealing with tags can't result in spaghetti code or unintended behaviours.

    I left out registering and dequeuing the cell, but I'm sure you're all familiar with that. If not, just let me know and I'll try to walk you through it.

    0 讨论(0)
  • 2020-12-29 17:24

    If you really want to insert an collectionView inside a collectionViewCell then there is a pretty simple step. Create an instance of UICollectionView and add it the collectionViewCell. You can use this example if you like.

    //
    //  ViewController.swift
    //  StackOverFlowAnswer
    //
    //  Created by BIKRAM BHANDARI on 18/6/17.
    //  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
    //
    
    import UIKit
    
    class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
        let cellId = "CellId"; //Unique cell id
    
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .red; //just to test
    
            collectionView.register(Cell.self, forCellWithReuseIdentifier: cellId) //register collection view cell class
            setupViews(); //setup all views
        }
    
        func setupViews() {
    
            view.addSubview(collectionView); // add collection view to view controller
            collectionView.delegate = self; // set delegate
            collectionView.dataSource = self; //set data source
    
            collectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true; //set the location of collection view
            collectionView.rightAnchor.constraint(equalTo:  view.rightAnchor).isActive = true; // top anchor of collection view
            collectionView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true; // height
            collectionView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true; // width
    
        }
    
        let collectionView: UICollectionView = { // collection view to be added to view controller
            let cv = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()); //zero size with flow layout
            cv.translatesAutoresizingMaskIntoConstraints = false; //set it to false so that we can suppy constraints
            cv.backgroundColor = .yellow; // test
            return cv;
        }();
    
        //deque cell
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath);
    //        cell.backgroundColor = .blue;
            return cell;
        }
    
        // number of rows
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 5;
        }
    
        //size of each CollecionViewCell
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            return CGSize(width: view.frame.width, height: 200);
        }
    }
    
    // first UICollectionViewCell
    class Cell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
    
        let cellId = "CellId"; // same as above unique id
    
        override init(frame: CGRect) {
            super.init(frame: frame);
    
            setupViews();
            collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId); //register custom UICollectionViewCell class.
            // Here I am not using any custom class
    
        }
    
    
        func setupViews(){
            addSubview(collectionView);
    
            collectionView.delegate = self;
            collectionView.dataSource = self;
    
            collectionView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true;
            collectionView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true;
            collectionView.topAnchor.constraint(equalTo: topAnchor).isActive = true;
            collectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true;
        }
    
        let collectionView: UICollectionView = {
            let layout = UICollectionViewFlowLayout();
            layout.scrollDirection = .horizontal; //set scroll direction to horizontal
            let cv = UICollectionView(frame: .zero, collectionViewLayout: layout);
            cv.backgroundColor = .blue; //testing
            cv.translatesAutoresizingMaskIntoConstraints = false;
            return cv;
        }();
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath);
            cell.backgroundColor = .red;
            return cell;
        }
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 5;
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            return CGSize(width: self.frame.width, height: self.frame.height - 10);
        }
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    0 讨论(0)
  • 2020-12-29 17:28

    There are multiple ways to tackle the problem of a horizontal collection inside another a vertical list collection.

    The simplest would be to make the ViewController you are presenting the main UICollectionView to the dataSouce and delegate for both collection views. You can set the collection view inside the cell also to be served from here.

    This article about placing collection view inside a table view explains the problem in a much elaborate way and the code for the same can be found here.

    0 讨论(0)
提交回复
热议问题