Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView reuse in UITableViewCell

I know this question is already ask many times but non of the solution will work.

I have collection view in uitableview cell and i prepare a cell of table view and collection view in story board and my problem is that suppose i scroll cell 1 collection view then cell 4 collection is auto scroll to that position also. How i can handle this situation..

Please note right now i make a static design of the screen

My code

// MARK:
    // MARK: table view delegate method

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

        if Appconstant.isIpad()
        {
            return 215.0
        }
        return 185.0

    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 6
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let strCell = "WorkoutCell" //+ "\(indexPath.row)"
        let cell = tableView.dequeueReusableCellWithIdentifier(strCell) as? WorkoutCell
//        if cell == nil
//        {
//            cell = work 
//        }
        return cell!
    }
    func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        let cell2 = cell as! WorkoutCell
        cell2.collecionWorkout.reloadData()
    }
    // MARK:
    // MARK: collectionview delegate and data source
    //1
    func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
        return true
    }
     func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    //2
     func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsetsMake(0.0, 10.0, 0.0, 10.0)
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: NSIndexPath) -> CGSize {
        // Adjust cell size for orientation
        if Appconstant.isIpad() {
            return CGSize(width: 160, height: 150)
        }
        return CGSize(width: 140.0, height: 130.0)
    }
    //3
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("WorkoutCollectionCell", forIndexPath: indexPath)
        // Configure the cell
        return cell
    }

uitableview cell code

class WorkoutCell: UITableViewCell {

    @IBOutlet weak var collecionWorkout: UICollectionView!
    var flowLayout : UICollectionViewFlowLayout!
    override func awakeFromNib() {
        super.awakeFromNib()
        self.flowLayout = UICollectionViewFlowLayout()
        if Appconstant.isIpad()
        {
            self.flowLayout.itemSize = CGSize(width: 160, height: 150)
        }
        else
        {
            self.flowLayout.itemSize = CGSize(width: 140, height: 130)
        }
        self.flowLayout.scrollDirection = .Horizontal
        self.flowLayout.minimumInteritemSpacing = 10.0
        flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 10.0, 0.0, 10.0);
        collecionWorkout.collectionViewLayout = flowLayout

        // Initialization code
    }

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

        // Configure the view for the selected state
    }

}

Cell 1st which i scroll

enter image description here

cell 4th which auto scroll

enter image description here

like image 480
chirag shah Avatar asked Sep 25 '16 18:09

chirag shah


2 Answers

There are two scenarios.

1 - Reset The UICollectionView offset position :

To Reset the collectionview position just call cell.collectionView.contentOffset = .zero in cellForRowAtIndexPath

2 - Maintain the previous scroll position :

To Maintain the previous scroll position, You'll need to have a list of offsets for each cell stored alongside your data models in the containing view controller. Then you might save the offset for a given cell in didEndDisplayingCell and setting it in cellForRowAtIndexPath instead of .zero .

like image 184
Taimoor Suleman Avatar answered Oct 19 '22 22:10

Taimoor Suleman


UITableView works on the concept of reusability. Whenever the tableView is scrolled, the cells in the tableView will definitely be reused.

Now 2 scenarios arise with this,

  1. Get a new cell - When the tableViewCell is reused, the collectionView inside it also will be reused and so this is the reason the contentOffset of the previous cell is retained.

  2. Scroll to previous cell - if we've manually scrolled to a particular cell in the collectionView, we might want to retain its position when we scroll back to it.

To get this kind of functionality in tableView, we need to - manually reset the contentOffset for 1st case and need to retain the contentOffset in the 2nd one.

Another approach you can follow is using a combination of UIScrollview and UIStackView.

This is how it goes.

  1. In storyboard, create a UIScrollView. Add a vertical UIStackView to it.

  2. Add 4 UICollectionViews in the stackView. This number is configurable as per your requirement.

  3. Add your controller as the dataSource and delegate of all the collectionViews.

i.e.

class ViewController: UIViewController, UICollectionViewDataSource {
    override func viewDidLoad() {
        super.viewDidLoad()
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
        cell.label.text = "\(indexPath.row)"
        return cell
    }
}

class CustomCell: UICollectionViewCell {
    @IBOutlet weak var label: UILabel!
}

Now, since we're using a stackView, none of the collectionViews will be reused. So, the contentOffsets of the all the collectionViews will remain intact.

enter image description here

like image 42
PGDev Avatar answered Oct 19 '22 23:10

PGDev