UICollectionView Cell Structure Animation Affects Multiple Cells

Hi There,

As in Title, when animating a cell structure (simply moving a UIImageView up 50 points) in one cell it affects some other cells too which are offscreen, scrolling to other cells reveals the same "quantum entanglement" if you like :-)

I am aware that for a number of reasons the cell instance is reused for other index items, and I can see this in the debugging, the affected cells all have the same cell reference. customCell: 0x7ff2c670b560 (when last run). I appreciate this is by design that the cells operate this way.

My question is simple (I hope) - Is there any way to decouple an animation on a cell that is visible on screen from a cell out of view? Is there an "Apple" way to do this?

spent days searching on forums so far but no cigarillo!

Thanks in advance for any input.


No, that should not do this, you have a design, error somewhere.

Could you show
  • how and where you do the animation ?

  • On which event ?

Is it when you select the cell ?

Here is an example (for a collectionView, but transpose directly to tableView cell:

Code Block
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCollectionItem = indexPath.row
let cell = collectionView.cellForItem(at: indexPath)
UIView.animate(withDuration: 2.0, delay: 0.0, options: .curveEaseOut, animations: {
cell?.layer.zPosition = cell!.isSelected ? 1 : -1
cell?.transform = cell!.isSelected ? CGAffineTransform(scaleX: 1.5, y: 1.5) : CGAffineTransform.identity
}, completion: { (done) in
cell?.transform = CGAffineTransform.identity
self.performSegue(withIdentifier: "SomeSegue", sender:self) }). // I segue once animation done
}

Hi Claude,

Thanks for taking the time to respond, much appreciated.

The animation is activated by the didselect function as in your sample code.

I should clarify that unlike your animation, my animation does not return to its original value, unless another event happens. so its state remains, and this is reflected in other cells off screen if you scroll, which I am pretty sure is normal behaviour for reused cells?
For clarity here is a cut down version of my controller and cell Code.

Code Block class ViewController: UIViewController {
    
    var collectionView: UICollectionView!
    var cellScale : CGFloat = 0.67
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let screenSize = UIScreen.main.bounds.size
        let cellWidth = floor(screenSize.width * cellScale )
        let cellHeight = floor(screenSize.height * cellScale)
        
        let view = UIView()
        view.backgroundColor = .white
               
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
        layout.itemSize = CGSize(width: cellWidth, height: cellHeight )
        layout.scrollDirection = .horizontal
               
        collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        collectionView?.register(customCell.self, forCellWithReuseIdentifier: "customCell")
        collectionView?.backgroundColor = UIColor.white
        collectionView?.dataSource = self
        collectionView?.delegate = self
        
        view.addSubview(collectionView ?? UICollectionView())
               
            self.view = view
    }
}
extension ViewController: UICollectionViewDataSource {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        
        return 10
    }
   
    
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCell", for: indexPath) as! customCell
        cell.labelRow1.text = String(indexPath.row + 1)
        
        
        return cell
    }
}
extension ViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print(indexPath.row + 1)
        
        let cell = collectionView.cellForItem(at: indexPath) as! customCell
        
        UIView.animate(withDuration: 2.0, delay: 0.0, options: .curveEaseOut, animations: {
            cell.iv.center.y = cell.isSelected ? 1 : -1
                    cell.transform = cell.isSelected ? CGAffineTransform(scaleX: 1.1, y: 1.1) : CGAffineTransform.identity
                }, completion: nil)
        
    }
}


CELL CODE

Code Block import Foundation
import UIKit
class customCell: UICollectionViewCell {
    
    override func prepareForReuse() {
        super.prepareForReuse()
                      
    }
        
   
    let iv = UIImageView()
    let labelRow1 = UILabel()
   
    
    override init(frame: CGRect) {
        super.init(frame: .zero)
        configure()
    }
    required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
    }
        
}
extension customCell {
    
  
    func configure() {
        print("configuring custom cell")
               
       
        labelRow1.translatesAutoresizingMaskIntoConstraints = false
        labelRow1.backgroundColor = .lightGray
        labelRow1.textAlignment = .center
        labelRow1.clipsToBounds = true
        labelRow1.layer.borderWidth = 0.6
        labelRow1.layer.borderColor = UIColor.systemGray.cgColor
        labelRow1.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
        contentView.addSubview(labelRow1)
        
        
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.backgroundColor = .blue
        iv.isUserInteractionEnabled = true
        iv.clipsToBounds = true
        iv.layer.cornerRadius = 12
        iv.layer.borderColor = UIColor.systemGray.cgColor
        iv.layer.borderWidth = 0.6
        iv.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
        contentView.addSubview(iv)   
 
        
        
        NSLayoutConstraint.activate([
                        
        iv.topAnchor.constraint(equalTo: contentView.topAnchor),
        iv.leftAnchor.constraint(equalTo: contentView.leftAnchor),
        iv.rightAnchor.constraint(equalTo: contentView.rightAnchor),
        iv.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.55),
        labelRow1.topAnchor.constraint(equalTo: iv.bottomAnchor),
        labelRow1.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
        labelRow1.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
        labelRow1.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.15),
            
      
    
        ])
    }
    
}





UICollectionView Cell Structure Animation Affects Multiple Cells
 
 
Q