Specifying one Dimension of Cells in UICollectionView using Auto Layout

前端 未结 5 1674
执念已碎
执念已碎 2020-11-30 16:01

In iOS 8 the UICollectionViewFlowLayout supports automatically resizing cells based on their own content size. This resizes the cells in both width and height a

5条回答
  •  温柔的废话
    2020-11-30 16:47

    There's a cleaner way to do this than some of the other answers here, and it works well. It should be performant (collection views load fast, no unnecessary auto layout passes etc), and doesn't have any 'magic numbers' like a fixed collection view width. Changing the collection view size, e.g. on rotation, and then invalidating the layout should work great too.

    1. Create the following flow layout subclass

    class HorizontallyFlushCollectionViewFlowLayout: UICollectionViewFlowLayout {
    
        // Don't forget to use this class in your storyboard (or code, .xib etc)
    
        override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
            let attributes = super.layoutAttributesForItemAtIndexPath(indexPath)?.copy() as? UICollectionViewLayoutAttributes
            guard let collectionView = collectionView else { return attributes }
            attributes?.bounds.size.width = collectionView.bounds.width - sectionInset.left - sectionInset.right
            return attributes
        }
    
        override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            let allAttributes = super.layoutAttributesForElementsInRect(rect)
            return allAttributes?.flatMap { attributes in
                switch attributes.representedElementCategory {
                case .Cell: return layoutAttributesForItemAtIndexPath(attributes.indexPath)
                default: return attributes
                }
            }
        }
    }
    

    2. Register your collection view for automatic sizing

    // The provided size should be a plausible estimate of the actual
    // size. You can set your item size in your storyboard
    // to a good estimate and use the code below. Otherwise,
    // you can provide it manually too, e.g. CGSize(width: 100, height: 100)
    
    flowLayout.estimatedItemSize = flowLayout.itemSize
    

    3. Use the predefined width + custom height in your cell subclass

    override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
        layoutAttributes.bounds.size.height = systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
        return layoutAttributes
    }
    

提交回复
热议问题