Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/109.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UICollectionView自定义布局中间列的起点更高_Ios_Swift_Uicollectionview - Fatal编程技术网

Ios UICollectionView自定义布局中间列的起点更高

Ios UICollectionView自定义布局中间列的起点更高,ios,swift,uicollectionview,Ios,Swift,Uicollectionview,我现在有一个垂直滚动的UICollectionView。我想让它看起来像这样,中间一行比其他两行高一点,以创造一个酷而有趣的效果。 关于如何实现这一点有什么想法吗 可以通过创建一个集合视图来实现集合视图布局 理论: 基本上,集合视图直接使用自定义布局对象来管理整个布局过程,要求提供所需的布局信息 在布局过程中,集合视图调用布局对象的特定方法。这些方法提供了计算项目位置的机会,并为集合视图提供它所需的主要信息 在布局过程中,始终按顺序调用以下方法: :执行提供布局信息所需的前期计算 :返回基于初始

我现在有一个垂直滚动的UICollectionView。我想让它看起来像这样,中间一行比其他两行高一点,以创造一个酷而有趣的效果。 关于如何实现这一点有什么想法吗


可以通过创建一个集合视图来实现集合视图布局

理论:

基本上,集合视图直接使用自定义布局对象来管理整个布局过程,要求提供所需的布局信息

在布局过程中,集合视图调用布局对象的特定方法。这些方法提供了计算项目位置的机会,并为集合视图提供它所需的主要信息

在布局过程中,始终按顺序调用以下方法:

  • :执行提供布局信息所需的前期计算
  • :返回基于初始计算的整个内容区域的总大小
  • :返回指定矩形中的单元格和视图的属性

  • 实用性:

  • 先决条件:假设我们有一个集合视图,并配置了 数据源和代理,让我们创建一个
    UICollectionViewLayout
    子类。我把它命名为HiveLayout。我还把它分配给了 故事板中的集合视图。我们还需要一些在这个过程中有用的变量

    //    Properties for configuring the layout: the number of columns and the cell padding.
    fileprivate var numberOfColumns = 3
    fileprivate var cellPadding: CGFloat = 10
    
    //    Cache the calculated attributes. When you call prepare(), you’ll calculate the attributes for all items and add them to the cache. You can be efficient and query the cache instead of recalculating them every time.
    fileprivate var cache = [UICollectionViewLayoutAttributes]()
    
    //    Properties to store the content size.
    fileprivate var contentHeight: CGFloat = 0
    fileprivate var contentWidth: CGFloat {
        guard let collectionView = collectionView else {
            return 0
        }
        let insets = collectionView.contentInset
        return collectionView.bounds.width - (insets.left + insets.right)
    }
    
  • :这是我们实际计算单元格属性的地方

    override func prepare() {
        // If cache is empty and the collection view exists – calculate the layout attributes
        guard cache.isEmpty == true, let collectionView = collectionView else {
            return
        }
    
        // xOffset: array with the x-coordinate for every column based on the column widths
        // yOffset: array with the y-position for every column, Using odd-even logic to push the even cell upwards and odd cells down.
        let columnWidth = contentWidth / CGFloat(numberOfColumns)
        var xOffset = [CGFloat]()
        for column in 0 ..< numberOfColumns {
            xOffset.append(CGFloat(column) * columnWidth)
        }
        var column = 0
    
        var yOffset = [CGFloat]()
        for i in 0..<numberOfColumns {
            yOffset.append((i % 2 == 0) ? (columnWidth / 2) : 0)
        }
    
        for item in 0 ..< collectionView.numberOfItems(inSection: 0) {
    
            let indexPath = IndexPath(item: item, section: 0)
    
            // Calculate insetFrame that can be set to the attribute
            let cellHeight = columnWidth - (cellPadding * 2)
            let height = cellPadding * 2 + cellHeight
            let frame = CGRect(x: xOffset[column], y: yOffset[column], width: columnWidth, height: height)
            let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
    
            // Create an instance of UICollectionViewLayoutAttribute, sets its frame using insetFrame and appends the attributes to cache.
            let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes.frame = insetFrame
            cache.append(attributes)
    
            // Update the contentHeight to account for the frame of the newly calculated item. It then advances the yOffset for the current column based on the frame
            contentHeight = max(contentHeight, frame.maxY)
            yOffset[column] = yOffset[column] + height
    
            column = column < (numberOfColumns - 1) ? (column + 1) : 0
        }
    }
    
  • override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    
        var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
    
        for attributes in cache {
            if attributes.frame.intersects(rect) {
                visibleLayoutAttributes.append(attributes)
            }
        }
        return visibleLayoutAttributes
    }
    
  • :返回特定单元格的属性

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        return cache[indexPath.item]
    }
    
  • 请查看布局类的

    在这里,它正在发挥作用


    我如何才能使第一个单元格位于顶部而不是右侧?我很乐意提供帮助,你能详细说明吗?现在第一个单元格位于右侧栏中,我想让中间栏先填充,如果可能的话,你知道我可以怎么做吗?我相信这是可以实现的,你能试着修改上面的代码吗?检查
    xOffset
    yOffset
    值是否有帮助。需要一些数学知识。。
    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        return cache[indexPath.item]
    }