By default Collection View maintains content offset while inserting cells. On the other hand I\'d like to insert cells above the currently displaying ones so that they appea
Here's a slightly tweaked version of Peter's solution (subclassing flow layout, no upside-down, lightweight approach). It's Swift 3. Note UIView.animate with zero duration - that's to allow the animation of the even/oddness of the cells (what's on a row) animate, but stop the animation of the viewport offset changing (which would look terrible)
Usage:
let layout = self.collectionview.collectionViewLayout as! ContentSizePreservingFlowLayout
layout.isInsertingCellsToTop = true
self.collectionview.performBatchUpdates({
if let deletionIndexPaths = deletionIndexPaths, deletionIndexPaths.count > 0 {
self.collectionview.deleteItems(at: deletionIndexPaths.map { return IndexPath.init(item: $0.item+twitterItems, section: 0) })
}
if let insertionIndexPaths = insertionIndexPaths, insertionIndexPaths.count > 0 {
self.collectionview.insertItems(at: insertionIndexPaths.map { return IndexPath.init(item: $0.item+twitterItems, section: 0) })
}
}) { (finished) in
completionBlock?()
}
Here's ContentSizePreservingFlowLayout in its entirety:
class ContentSizePreservingFlowLayout: UICollectionViewFlowLayout {
var isInsertingCellsToTop: Bool = false {
didSet {
if isInsertingCellsToTop {
contentSizeBeforeInsertingToTop = collectionViewContentSize
}
}
}
private var contentSizeBeforeInsertingToTop: CGSize?
override func prepare() {
super.prepare()
if isInsertingCellsToTop == true {
if let collectionView = collectionView, let oldContentSize = contentSizeBeforeInsertingToTop {
UIView.animate(withDuration: 0, animations: {
let newContentSize = self.collectionViewContentSize
let contentOffsetY = collectionView.contentOffset.y + (newContentSize.height - oldContentSize.height)
let newOffset = CGPoint(x: collectionView.contentOffset.x, y: contentOffsetY)
collectionView.contentOffset = newOffset
})
}
contentSizeBeforeInsertingToTop = nil
isInsertingCellsToTop = false
}
}
}