Filling a UICollectionView in Reverse Order

I would like to populate the UICollectionView in reverse order, so that the last element of the UICollectionView populates first, then the second and so on. In fact, I apply animation, and objects appear one at a time. So I want the last item to be displayed first.

+6
source share
8 answers

I assume that you are using UICollectionViewFlawLayout, and it has no logic for this, it only works in TOP-LEFT BOTTOM-RIGHT order. To do this, you need to create your own layout, which you can create when creating a new object that inherits from UICollectionViewLayout.

, , , 4 , .

: https://developer.apple.com/library/prerelease/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html

+1

, Apple UICollectionViewLayout . . , , , . , , , . , .

, , , . , , , Apple , prepare() .

Swift 3.0.

//
//  Created by John Lyon-Smith on 1/7/17.
//  Copyright Β© 2017 John Lyon-Smith. All rights reserved.
//

import Foundation
import UIKit

class InvertedStackLayout: UICollectionViewLayout {
    let cellHeight: CGFloat = 100.00 // Your cell height here...

    override func prepare() {
        super.prepare()
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var layoutAttrs = [UICollectionViewLayoutAttributes]()

        if let collectionView = self.collectionView {
            for section in 0 ..< collectionView.numberOfSections {
                if let numberOfSectionItems = numberOfItemsInSection(section) {
                    for item in 0 ..< numberOfSectionItems {
                        let indexPath = IndexPath(item: item, section: section)
                        let layoutAttr = layoutAttributesForItem(at: indexPath)

                        if let layoutAttr = layoutAttr, layoutAttr.frame.intersects(rect) {
                            layoutAttrs.append(layoutAttr)
                        }
                    }
                }
            }
        }

        return layoutAttrs
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let layoutAttr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
        let contentSize = self.collectionViewContentSize

        layoutAttr.frame = CGRect(
            x: 0, y: contentSize.height - CGFloat(indexPath.item + 1) * cellHeight,
            width: contentSize.width, height: cellHeight)

        return layoutAttr
    }

    func numberOfItemsInSection(_ section: Int) -> Int? {
        if let collectionView = self.collectionView,
            let numSectionItems = collectionView.dataSource?.collectionView(collectionView, numberOfItemsInSection: section)
        {
            return numSectionItems
        }

        return 0
    }

    override var collectionViewContentSize: CGSize {
        get {
            var height: CGFloat = 0.0
            var bounds = CGRect.zero

            if let collectionView = self.collectionView {
                for section in 0 ..< collectionView.numberOfSections {
                    if let numItems = numberOfItemsInSection(section) {
                        height += CGFloat(numItems) * cellHeight
                    }
                }

                bounds = collectionView.bounds
            }

            return CGSize(width: bounds.width, height: max(height, bounds.height))
        }
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        if let oldBounds = self.collectionView?.bounds,
            oldBounds.width != newBounds.width || oldBounds.height != newBounds.height
        {
            return true
        }

        return false
    }
}
+3

UICollectionView , Force

, , :

image for right to left in inspector

+2

, . :

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

, . - , . CoreData.

let desiredIndex = dataProfile!.itemEntries!.count - indexPath[1] - 1;
+1

Swift 4.2

:

viewDidLoad():

collectionView.transform = CGAffineTransform.init(rotationAngle: (-(CGFloat)(Double.pi)))

collectionView (_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) :

cell.transform = CGAffineTransform(rotationAngle: CGFloat.pi)

() .

:

   if self.dataCollection.count > 0 {
      self.collectionView.scrollToItem(at: //scroll collection view to indexpath
      NSIndexPath.init(row:(self.collectionView?.numberOfItems(inSection: 0))!-1, //get last item of self collectionview (number of items -1)
      section: 0) as IndexPath //scroll to bottom of current section
      , at: UICollectionView.ScrollPosition.bottom, //right, left, top, bottom, centeredHorizontally, centeredVertically
      animated: true)
   }
+1

, , , .

, , UICollectionViewLayout.

-, :

-(void)viewWillAppear:(BOOL)animated {
    [self.view layoutIfNeeded]; //for letting the compiler know the actual height and width of your collection view before we start to operate with it
    if (self.collectionView.frame.size.height > self.collectionView.collectionViewLayout.collectionViewContentSize.height) {
        self.collectionViewTopConstraint.constant = self.collectionView.frame.size.height - self.collectionView.collectionViewLayout.collectionViewContentSize.height;
    }

, , . . . , . , . , .

0

, :

yourCollectionView.inverted = true

PS: /IGListKit..

0

Why don't you just cancel your data source? If you use an array, you can cancel it using

[[array reverseObjectEnumerator] allObjects]
-3
source

All Articles