【问题标题】:UICollectionViewCompositionalLayout - center items in sections or groupsUICollectionViewCompositionalLayout - 部分或组中的中心项目
【发布时间】:2020-11-23 09:13:09
【问题描述】:

我用新的组合材料设置了一个集合视图及其布局,它非常酷,它似乎非常可扩展,但我找不到使项目在集合中居中的方法,这是 IMO可以想象得到支持的基本功能..

我拥有的是:

使用此代码完成:

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
}

但我需要的是这个:

有没有人遇到过这种情况?谢谢

【问题讨论】:

  • stackoverflow.com/questions/13588283/… 第二种解决方案可以帮助您
  • 谢谢,如果组合布局无能为力,这实际上是我将依赖的解决方案
  • @nknr 你有没有找到解决方案,使用组合布局?
  • @AshleyMills IIRC 很遗憾,没有。我想我只是把它扔掉了,并采用了经典的布局

标签: ios swift uicollectionview uikit uicollectionviewcompositionallayout


【解决方案1】:

我找到了解决方案,使用

custom(layoutSize: NSCollectionLayoutSize, itemProvider: @escaping NSCollectionLayoutGroupCustomItemProvider)

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

extension NSCollectionLayoutGroup {

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

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

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

然后创建布局……

func makeLayout() -> UICollectionViewLayout {
    UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in

        let section = diffableDataSource.snapshot().sectionIdentifiers[sectionIndex]

        switch section {
        case .someSection:
            return someLayoutSection(sectionIndex: sectionIndex)
        case .otherSection:
            // etc
        }
    }

【讨论】:

  • 看起来不错! (次要,但不应该是.horizontallyCentered()吗?)不管怎样,谢谢
猜你喜欢
  • 2022-07-15
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多