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

Chr*_*hen 8 ios uicollectionview

所以,我正在尝试使用UICollectionView实现标记列表.我正在学习本教程:http://www.cocoanetics.com/2013/08/variable-sized-items-in-uicollectionview/

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

在此输入图像描述

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

但我真正想要实现的是这样的:

在此输入图像描述

有任何想法吗?

Cœu*_*œur 10

我已将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
    }
}
Run Code Online (Sandbox Code Playgroud)


Bra*_*adB 1

苹果为我们开发者提供了 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/

希望有帮助。