UICollectionViewCompositionalLayout - 在部分或组中居中项目

nkn*_*knr 5 uikit ios uicollectionview swift uicollectionviewcompositionallayout

我使用新的组合内容设置了一个集合视图及其布局,它非常酷,它似乎非常可扩展,但我找不到一种方法使项目集中在集合中,这是我认为的一个基本功能人们会想象得到支持..

我所拥有的是:

在此输入图像描述

使用此代码完成:

UICollectionViewCompositionalLayout { section, env in
    let tagDefaultSize = CGSize(width: 100, height: 40)
    
    let item = NSCollectionLayoutItem(
        layoutSize: NSCollectionLayoutSize(widthDimension: .estimated(tagDefaultSize.width), heightDimension: .absolute(tagDefaultSize.height))
    )
    
    item.edgeSpacing = NSCollectionLayoutEdgeSpacing(
        leading: .fixed(0),
        top: .fixed(0),
        trailing: .fixed(8),
        bottom: .fixed(0)
    )
    
    let group = NSCollectionLayoutGroup.horizontal(
        layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(tagDefaultSize.height)),
        subitems: [item]
    )
    
    group.edgeSpacing = NSCollectionLayoutEdgeSpacing(
        leading: .flexible(8),
        top: .fixed(0),
        trailing: .fixed(8),
        bottom: .fixed(8)
    )
    
    let section = NSCollectionLayoutSection(group: group)
    
    section.contentInsets = NSDirectionalEdgeInsets(
        top: 30,
        leading: 20,
        bottom: 40,
        trailing: 20
    )
    
    return section
}
Run Code Online (Sandbox Code Playgroud)

但我需要的是这样的:

在此输入图像描述

有人有这样的运气吗?谢谢

Ash*_*lls 8

我找到了一个解决方案,使用

\n
custom(layoutSize: NSCollectionLayoutSize, itemProvider: @escaping NSCollectionLayoutGroupCustomItemProvider)\n
Run Code Online (Sandbox Code Playgroud)\n

我创建了以下扩展,它计算组中每个元素的框架,将每行适合的尽可能多的项目居中

\n
extension NSCollectionLayoutGroup {\n\n    static func verticallyCentered(cellSizes: [CGSize], interItemSpacing: CGFloat = 10, interRowSpacing: CGFloat = 10) -> NSCollectionLayoutGroup {\n        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(100))\n        return custom(layoutSize: groupSize) { environment in\n            var items: [NSCollectionLayoutGroupCustomItem] = []\n            \n            var yPos: CGFloat = environment.container.contentInsets.top\n            \n            var rowSizes: [CGSize] = []\n            \n            func totalWidth() -> CGFloat {\n                rowSizes.map(\\.width).reduce(0) {\n                    $0 == 0 ? $1 : $0 + interItemSpacing + $1\n                }\n            }\n            \n            func addRowItems() {\n                var xPos = (environment.container.effectiveContentSize.width - totalWidth())/2 + environment.container.contentInsets.leading\n                let maxItemHeight = rowSizes.map(\\.height).max() ?? 0\n                let rowItems: [NSCollectionLayoutGroupCustomItem] = rowSizes.map {\n                    let rect = CGRect(origin: CGPoint(x: xPos, y: yPos + (maxItemHeight - $0.height) / 2), size: $0)\n                    xPos += ($0.width + interItemSpacing)\n                    return NSCollectionLayoutGroupCustomItem(frame: rect)\n                }\n                \n                items.append(contentsOf: rowItems)\n            }\n            \n            for (index, cellSize) in cellSizes.enumerated() {\n                rowSizes.append(cellSize)\n                \n                if totalWidth() > environment.container.effectiveContentSize.width {\n                    rowSizes.removeLast()\n                    addRowItems()\n                    yPos += (cellSize.height + interRowSpacing)\n                    rowSizes = [cellSize]\n                }\n                \n                if index == cellSizes.count - 1 {\n                    addRowItems()\n                }\n            }\n            return items\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后创建一个布局部分,其中包含一个包含该部分中所有项目的组。首先,您首先需要计算该部分中所有元素的大小,然后将它们传递给上面的函数,如下所示(请注意,我在这里使用 DiffableDataSource)\xe2\x80\xa6

\n
func someLayoutSection(sectionIndex: Int) -> NSCollectionLayoutSection {\n    let itemCount = collectionView.numberOfItems(inSection: sectionIndex)\n    let cell = SomeCell(frame: .zero)\n    let cellSizes: [CGSize] = (0..<itemCount).compactMap {\n        switch diffableDataSource.itemIdentifier(for: IndexPath(item: $0, section: sectionIndex)) {\n        case let .someItem(something):\n            cell.configure(thing: something)\n            return cell.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)\n        default:\n            return nil\n        }\n    }\n    \n    let group = NSCollectionLayoutGroup.verticallyCentered(cellSizes: cellSizes)\n    group.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20).scaled\n    \n    let section = NSCollectionLayoutSection(group: group)\n    section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 0, bottom: 20, trailing: 0)\n    return section\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后创建布局\xe2\x80\xa6

\n
func makeLayout() -> UICollectionViewLayout {\n    UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in\n\n        let section = diffableDataSource.snapshot().sectionIdentifiers[sectionIndex]\n\n        switch section {\n        case .someSection:\n            return someLayoutSection(sectionIndex: sectionIndex)\n        case .otherSection:\n            // etc\n        }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n