CollectionView不同大小,没有任何库

时间:2018-12-12 10:53:15

标签: ios swift

我正在尝试设计一个集合视图,其布局会如所附图像中所示发生变化。如果有人对此设计有任何想法,请提供帮助。

预先感谢

Screen Shot

我需要这种类型的布局才能在没有任何库的情况下收集视图

1 个答案:

答案 0 :(得分:1)

  • 您需要创建UICollectionViewLayout的子类,并且需要 覆盖准备方法。

  • 计算UICollectionViewLayoutAttributes的框架并将其存储在 缓存字典。

  • 实现layoutAttributesForElements和layoutAttributesForItem 缓存字典的方法

这里是代码,请检查:

import UIKit

class MJCollectionLayout: UICollectionViewLayout {
    fileprivate var cache = [IndexPath: UICollectionViewLayoutAttributes]()
    fileprivate var cellPadding: CGFloat = 1
    fileprivate var contentHeight: CGFloat = 0
    var oldBound: CGRect!
    fileprivate var contentWidth: CGFloat {
        guard let collectionView = collectionView else {
            return 0
        }
        let insets = collectionView.contentInset
        return collectionView.bounds.width - (insets.left + insets.right)
    }

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

    override func prepare() {
        super.prepare()
        contentHeight = 0
        cache.removeAll(keepingCapacity: true)
        guard cache.isEmpty == true, let collectionView = collectionView else {
            return
        }
        if collectionView.numberOfSections == 0 {
            return
        }
        oldBound = self.collectionView?.bounds
        for item in 0 ..< collectionView.numberOfItems(inSection: 0) {
            let indexPath = IndexPath(item: item, section: 0)
            let cellSize = self.getCellSize(index: item)
            let origin = self.getOrigin(index: item)
            let frame = CGRect(origin: origin, size: cellSize)
            let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
            let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes.frame = insetFrame
            cache[indexPath] = (attributes)
            contentHeight = max(contentHeight, frame.maxY)
        }
    }

    func getCellSize(index: Int) -> CGSize {
        let col = index % 6
        let width = contentWidth / 2.0
        if col == 2  {
            return CGSize.init(width: 2 * width, height: width)
        }
        if col == 4 {
            return CGSize.init(width:  width, height: 2 * width)
        }
        return CGSize.init(width: width, height: width)
    }

    func getOrigin(index: Int) -> CGPoint {
        let col = index % 6
        let multiplayer = index / 6
        let width = contentWidth / 2.0
        var y: CGFloat = 0.0
        var x: CGFloat = 0.0
        if col == 0 || col == 1 {
            y = CGFloat(multiplayer) * (8.0 * width) + 0
        }
        if col == 2 {
            y = CGFloat(multiplayer) * (8.0 * width) + width
        }
        if col == 3 || col == 4  {
            y = CGFloat(multiplayer) * (8.0 * width) + (2.0 * width)
        }
        if col == 5 {
             y = CGFloat(multiplayer) * (8.0 * width) + (3.0 * width)
        }
        if col == 0 || col == 2 || col == 3 || col == 5 {
            x = 0.0
        }
        if  col == 1 || col == 4 {
            x = width
        }

        return CGPoint(x: x, y: y)
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
        // Loop through the cache and look for items in the rect
        visibleLayoutAttributes = cache.values.filter({ (attributes) -> Bool in
            return attributes.frame.intersects(rect)
        })
        print(visibleLayoutAttributes)
        return visibleLayoutAttributes
    }

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

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        if newBounds.width != oldBound?.width {
            return true
        }
        return false
    }
}