23

When I call reloadData method of UICollectionView it cause all visible cell to blink. I found that reason of this is recreation of all visible cells, while UITableView return visible cell in – tableView:cellForRowAtIndexPath: method after reload data.

So, how can I avoid recreation of visible cells in UICollectionView.

Wain
  • 117,132
  • 14
  • 131
  • 151
abagmut
  • 731
  • 1
  • 6
  • 22

5 Answers5

19

You need to reload the visible cells, which will not cause the flash seen during reloadData:

[myCollectionView reloadItemsAtIndexPaths:[myCollectionView indexPathsForVisibleItems]];

Adam W. Dennis
  • 479
  • 4
  • 7
6

Calling reloadData on either a table or a collection view will recreate (dequeue if possible) all of the (visible) cells and refresh the information about the row / item count and the view content height. So, you will always see a 'blink' because it's animated.

This is by design to inform the user that everything was just updated...

To avoid animation, don't call reloadData. Instead, use visibleCells to get all of the cells that currently exist on the screen and update their contents directly.

Wain
  • 117,132
  • 14
  • 131
  • 151
  • When I call reloadData for tableView in `tableView:cellForRowAtIndexPath:` I get visible cell with previously loaded data. So, for example, if I have imageView and image don't change I don't update it and thus avoid blinking. But for collection view after reloadData I get entirely new cell - not currently visible cell with data previously loaded. – abagmut May 17 '14 at 19:44
  • Whether you 'get' a reusable cell is not specific to table or collection view, it's more related to what scrolling you've done or what previous reloads have happened. And you should always reconfigure the cell - how do you know which row it was previously used for... – Wain May 17 '14 at 20:12
  • I call reloadData when collectionView is not scrolling. It is not necessary to know for which row it was previously used for. Just save image name for image which are currently loaded in cell and if it match after reload (for tableView if cell dataSource not change - it's true) do nothing. – abagmut May 18 '14 at 06:17
4

Swift Version:

if let indexPaths = collectionView?.indexPathsForVisibleItems {
    collectionView?.reloadItems(at: indexPaths)
}
johndpope
  • 4,223
  • 2
  • 33
  • 37
4

You can simply create your own flow layout and set alpha to initial layout attribute, e.g.

class MyFlowLayout: UICollectionViewFlowLayout {

    override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attr = layoutAttributesForItem(at: itemIndexPath)
        attr?.alpha = 1
        return attr
    }
}

It's necessary because by default alpha is 0, and if cells are re-created - you see blinking.

Oleksandr
  • 391
  • 2
  • 5
1

You can try https://github.com/ba01ei/PSTImprovedCollectionView

With this collection view, when you call reloadData, if a cell is still visible, the same cell will be returned from the queue (then you can check the data model attached to the cell and decide whether to re-render)

Bao Lei
  • 3,195
  • 3
  • 17
  • 15