fgroeger
fgroeger

Reputation: 432

UICollectionView weird animation while performBatchUpdates

When calling performBatchUpdates on a horizontal scroll UICollectionView which has an contentOffset.x > 0, it executes a rather weird animation.

I recreated the error with a sample cell which shows exactly the error we get in our app. This happens also when there are no changes to be performed in performBatchUpdates at all. After completion, the items in the UICollectionView are correct, so it is just an animation problem.

Example GIF of behaviour

Did anybody face that issue already and has a solution for this?

My ViewController.swift:

class CollectionViewCell: UICollectionViewCell {
    @IBOutlet var label: UILabel!
}

class ViewController: UIViewController {
    @IBOutlet private var collectionView: UICollectionView!
    
    private var items: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let layout = UICollectionViewFlowLayout()
        layout.estimatedItemSize = CGSize(width: 1, height: 1)
        layout.scrollDirection = .horizontal
        
        collectionView.collectionViewLayout = layout
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
        collectionView.showsHorizontalScrollIndicator = false
    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        items.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? CollectionViewCell
        
        cell?.label.text = items[indexPath.row].description
        
        return cell ?? UICollectionViewCell()
    }
}

extension ViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        items.remove(at: indexPath.row)
        
        collectionView.performBatchUpdates({
            self.collectionView.deleteItems(at: [indexPath])
        }, completion: nil)
    }
}

Download example project here: https://wetransfer.com/downloads/74454a6b9df114529ba3a26b7b9488ab20200720141429/05eb4d

Upvotes: 1

Views: 1034

Answers (1)

vpoltave
vpoltave

Reputation: 1770

You have to set itemSize for you collectionView cell:

layout.itemSize = CGSize(width: 44, height: 44)

instead of(or in addition):

layout.estimatedItemSize = CGSize(width: 1, height: 1)

More about estimated and when you needed:
https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout/1617709-estimateditemsize

And itemSize:
https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout/1617711-itemsize

You are welcome!

Upvotes: 0

Related Questions