How do you determine spacing between cells in UICollectionView flowLayout

后端 未结 12 1196
夕颜
夕颜 2020-11-29 15:32

I have a UICollectionView with a flow layout and each cell is a square. How do I determine the spacing between each cells on each row? I can\'t seem to find the appropriate

12条回答
  •  失恋的感觉
    2020-11-29 16:03

    Clean Swift solution, from an history of evolution:

    1. there was matt answer
    2. there was Chris Wagner lone items fix
    3. there was mokagio sectionInset and minimumInteritemSpacing improvement
    4. there was fanpyi Swift version
    5. now here is a simplified and clean version of mine:
    open class UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout {
        open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            return super.layoutAttributesForElements(in: rect)?.map { $0.representedElementKind == nil ? layoutAttributesForItem(at: $0.indexPath)! : $0 }
        }
    
        open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
            guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes,
                collectionView != nil else {
                // should never happen
                return nil
            }
    
            // if the current frame, once stretched to the full row intersects the previous frame then they are on the same row
            if indexPath.item != 0,
                let previousFrame = layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame,
                currentItemAttributes.frame.intersects(CGRect(x: -.infinity, y: previousFrame.origin.y, width: .infinity, height: previousFrame.size.height)) {
                // the next item on a line
                currentItemAttributes.frame.origin.x = previousFrame.origin.x + previousFrame.size.width + evaluatedMinimumInteritemSpacingForSection(at: indexPath.section)
            } else {
                // the first item on a line
                currentItemAttributes.frame.origin.x = evaluatedSectionInsetForSection(at: indexPath.section).left
            }
            return currentItemAttributes
        }
    
        func evaluatedMinimumInteritemSpacingForSection(at section: NSInteger) -> CGFloat {
            return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, minimumInteritemSpacingForSectionAt: section) ?? minimumInteritemSpacing
        }
    
        func evaluatedSectionInsetForSection(at index: NSInteger) -> UIEdgeInsets {
            return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, insetForSectionAt: index) ?? sectionInset
        }
    }
    

    Usage: the spacing between items is determined by delegate's collectionView (_:layout:minimumInteritemSpacingForSectionAt:).

    I put it on github, https://github.com/Coeur/UICollectionViewLeftAlignedLayout, where I actually added a feature of supporting both scroll directions (horizontal and vertical).

提交回复
热议问题