Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom CollectionView Layout Reload Data not working

Upon creating a custom collection view layout reloadData does not work

Upon creating a custom collection view layout reloadData does not work after I did an infinite scroll which calls a new data from the api

I suspect that it is because of the fixed items called from the collectionview. How will I able to update it?

    protocol CustomCollectionViewLayoutDelegate: class {

        func collectionView(
            collectionView: UICollectionView,
            heightForItemAtIndexPath indexPath: IndexPath
        ) -> CGFloat

    }

    public class CustomCollectionViewLayout: UICollectionViewLayout {

        weak var delegate: CustomCollectionViewLayoutDelegate!
        public var numberOfColumns: Int = 1

        private var cache:  [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
        private var contentHeight: CGFloat = 0
        private var contentWidth: CGFloat {
            guard let collectionView = collectionView else {
                return 0
            }
            let insets = collectionView.contentInset
            return collectionView.bounds.width - (insets.left + insets.right)
        }


        public override var collectionViewContentSize: CGSize {
            return CGSize(
                width: self.contentWidth,
                height: self.contentHeight
            )
        }

        public override func prepare() {
            if cache.isEmpty {
                let columnWidth: CGFloat = self.contentWidth / CGFloat(self.numberOfColumns)
                var xOffset: [CGFloat] = [CGFloat]()

                for column in 0...numberOfColumns{
                    xOffset.append(CGFloat(column) * columnWidth)

                }

                var yOffset: [CGFloat] = [CGFloat](repeating: 0, count: self.numberOfColumns)

                var column: Int = 0

                for item in 0 ..< collectionView!.numberOfItems(inSection: 0) {
    //            for item in 0 ..< collectionView!.numberOfItems(inSection: 0) {
                    let indexPath: IndexPath = IndexPath(item: item, section: 0)
                    let height = delegate.collectionView(
                        collectionView: collectionView!,
                        heightForItemAtIndexPath: indexPath
                    )

                    let frame: CGRect = CGRect(
                        x: xOffset[column],
                        y: yOffset[column],
                        width: columnWidth,
                        height: height
                    )

                    let attributes: UICollectionViewLayoutAttributes = UICollectionViewLayoutAttributes(
                        forCellWith: indexPath
                    )

                    attributes.frame = frame
                    self.cache.append(attributes)
                    self.contentHeight = max(contentHeight, frame.maxY)
                    yOffset[column] = yOffset[column] + height

                    column = column < (self.numberOfColumns - 1) ? (column + 1) : 0

                }
            }
        }

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

            // Loop through the cache and look for items in the rect
            for attributes in cache {
                if attributes.frame.intersects(rect) {
                    visibleLayoutAttributes.append(attributes)
                }
            }

            return visibleLayoutAttributes
        }

        public override  func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
            return cache[indexPath.item]
        }

    }

I just need to be able to use reloadData to update my infinite scroll data

like image 413
user978064 Avatar asked Nov 18 '25 08:11

user978064


2 Answers

I suggest to add this function to your CustomCollectionViewLayout

func reloadData(){
    self.cache = [UICollectionViewLayoutAttributes]()
}

and then when you want to reload your data

    if let layout = self.collectionView.collectionViewLayout as? CustomCollectionViewLayout {
        layout.reloadData()
    }
collectionView.reloadData()

deleting if cache.isEmpty may result in reuse of your layout

like image 122
Amin Fadul Avatar answered Nov 20 '25 22:11

Amin Fadul


just remove if cache.isEmpty you should be fine

like image 33
Bruno Henrique Avatar answered Nov 20 '25 22:11

Bruno Henrique



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!