UICollectionView horizontal paging - can I use Flow Layout?

后端 未结 8 2086
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-07 09:27

This is related to but distinct from To use Flow Layout, or to Customize?.

Here is an illustration of what I’m trying to do:

8条回答
  •  自闭症患者
    2020-12-07 09:40

    The previous above implementation was not complete, buggy, and with fixed cell size. Here's a more literal translation for the code:

    import UIKit
    
    class HorizontalFlowLayout: UICollectionViewLayout {
        var itemSize = CGSizeZero {
            didSet {
                invalidateLayout()
            }
        }
        private var cellCount = 0
        private var boundsSize = CGSizeZero
    
        override func prepareLayout() {
            cellCount = self.collectionView!.numberOfItemsInSection(0)
            boundsSize = self.collectionView!.bounds.size
        }
    
        override func collectionViewContentSize() -> CGSize {
            let verticalItemsCount = Int(floor(boundsSize.height / itemSize.height))
            let horizontalItemsCount = Int(floor(boundsSize.width / itemSize.width))
    
            let itemsPerPage = verticalItemsCount * horizontalItemsCount
            let numberOfItems = cellCount
            let numberOfPages = Int(ceil(Double(numberOfItems) / Double(itemsPerPage)))
    
            var size = boundsSize
            size.width = CGFloat(numberOfPages) * boundsSize.width
            return size
        }
    
        override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            var allAttributes = [UICollectionViewLayoutAttributes]()
            for var i = 0; i < cellCount; i++ {
                let indexPath = NSIndexPath(forRow: i, inSection: 0)
                let attr = self.computeLayoutAttributesForCellAtIndexPath(indexPath)
                allAttributes.append(attr)
            }
            return allAttributes
        }
    
        override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
            return self.computeLayoutAttributesForCellAtIndexPath(indexPath)
        }
    
        override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
            return true
        }
    
        func computeLayoutAttributesForCellAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes {
            let row = indexPath.row
            let bounds = self.collectionView!.bounds
    
            let verticalItemsCount = Int(floor(boundsSize.height / itemSize.height))
            let horizontalItemsCount = Int(floor(boundsSize.width / itemSize.width))
            let itemsPerPage = verticalItemsCount * horizontalItemsCount
    
            let columnPosition = row % horizontalItemsCount
            let rowPosition = (row/horizontalItemsCount)%verticalItemsCount
            let itemPage = Int(floor(Double(row)/Double(itemsPerPage)))
    
            let attr = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
    
            var frame = CGRectZero
            frame.origin.x = CGFloat(itemPage) * bounds.size.width + CGFloat(columnPosition) * itemSize.width
            frame.origin.y = CGFloat(rowPosition) * itemSize.height
            frame.size = itemSize
            attr.frame = frame
    
            return attr
        }
    }
    

提交回复
热议问题