修复UICollectionView中项目与流布局之间的间距

时间:2014-07-07 10:33:54

标签: ios uicollectionview

因此,我尝试使用UICollectionView实现标记列表。我遵循本教程:http://www.cocoanetics.com/2013/08/variable-sized-items-in-uicollectionview/

问题是UICollectionView中的流布局尝试均匀地分隔同一行上的项目。

enter image description here

作为开发人员,我只能指定minimumInteritemSpacingForSectionAtIndex,它确实取决于UICollectionView以确定实际的项目间距。

但我真正想要实现的是:

enter image description here

有什么想法吗?

2 个答案:

答案 0 :(得分:8)

我已将Milo的解决方案转换为Swift:https://github.com/Coeur/UICollectionViewLeftAlignedLayout/

它只是子类UICollectionViewFlowLayout

import UIKit

/**
 *  Simple UICollectionViewFlowLayout that aligns the cells to the left rather than justify them
 *
 *  Based on https://stackoverflow.com/questions/13017257/how-do-you-determine-spacing-between-cells-in-uicollectionview-flowlayout
 */
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,
            let collectionView = self.collectionView else {
            // should never happen
            return nil
        }

        let sectionInset = evaluatedSectionInsetForSection(at: indexPath.section)

        guard indexPath.item != 0 else {
            currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset)
            return currentItemAttributes
        }

        guard let previousFrame = layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame else {
            // should never happen
            return nil
        }

        // if the current frame, once left aligned to the left and stretched to the full collection view
        // width intersects the previous frame then they are on the same line
        guard previousFrame.intersects(CGRect(x: sectionInset.left, y: currentItemAttributes.frame.origin.y, width: collectionView.frame.width - sectionInset.left - sectionInset.right, height: currentItemAttributes.frame.size.height)) else {
            // make sure the first item on a line is left aligned
            currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset)
            return currentItemAttributes
        }

        currentItemAttributes.frame.origin.x = previousFrame.origin.x + previousFrame.size.width + evaluatedMinimumInteritemSpacingForSection(at: indexPath.section)
        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
    }
}

extension UICollectionViewLayoutAttributes {
    func leftAlignFrame(withSectionInset sectionInset: UIEdgeInsets) {
        frame.origin.x = sectionInset.left
    }
}

答案 1 :(得分:0)

Apple为我们的开发人员提供了UICollectionViewFlowLayout类,这应该足以解决集合视图的“典型用例”。但是,我相信您的评估是正确的,默认布局不允许您创建此标签云效果。如果您需要与普通流布局不同的东西,则必须编写自己的UICollectionViewLayout子类。

Apple在2012年WWDC会议中介绍了这个主题,题为“高级集合视图和构建自定义布局”

其他一些Apple文档:https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html

冒着看似有偏见的风险,我还写了一篇快速的博客文章,贯穿基本步骤:http://bradbambara.wordpress.com/2014/05/24/getting-started-with-custom-uicollectionview-layouts/

希望有所帮助。