首页 > 解决方案 > 如何使用集合视图组合布局使集合视图内的单元格居中

问题描述

我有以下工作任务:我需要实现电影院视图,其中有一个屏幕和一组座位,每行代表一个部分:在此处输入图像描述

数据来自代表座位的二维数组:

var seats = [[1, 2, 3, 4, 5],
             [1, 2, 3, 4, 5],
            [1, 2, 3, 4, 5, 6],
            [1, 2, 3, 4, 5, 6],
            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
]

问题是我似乎无法找到如何使用组合布局在集合视图中将单元格居中。这是管理布局的代码:

private func createLayout() -> UICollectionViewLayout {
        let layout = UICollectionViewCompositionalLayout { [weak self] (section, configuration) -> NSCollectionLayoutSection? in
            guard let self = self else { return nil }
            
            // get the max seat number
            let max = CGFloat(self.seats.compactMap { $0.max() }.max()!)

            let itemSize = NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1.0 / max),
                heightDimension: .fractionalHeight(0.5))
            let item = NSCollectionLayoutItem(layoutSize: itemSize)
            item.contentInsets = .init(top: 2, leading: 2, bottom: 2, trailing: 2)

            let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                                                                         heightDimension: .fractionalWidth(0.2))

            let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

            let section = NSCollectionLayoutSection(group: group)
            section.contentInsets = .init(top: 16, leading: 32, bottom: 0, trailing: 32)
            
            return section
        }
        
        let config = UICollectionViewCompositionalLayoutConfiguration()
        config.interSectionSpacing = -50
        layout.configuration = config
        
        return layout
    }

我设法使用这样的“老式”集合视图流布局来实现此行为:

在此处输入图像描述

显然我不能使用 Collection View Flow Layout 的方法collectionView:layout:insetForSectionAtIndex:来计算这个,所以任何想法都会非常感激!

标签: iosswift

解决方案


让每一行,或至少每组具有相同数量项目的行,成为它自己的部分,并为布局提供部分提供程序功能。节提供者函数被赋予节号以及环境对象。从该环境对象中,您可以了解集合视图的宽度。现在只需给组或部分适当的插图。

为了说明,我能够实现这样的布局(三个部分,每个部分的项目数是部分索引加一):

在此处输入图像描述

我不会让你悬而未决;我将向您展示该布局的代码。它不漂亮;我使用了一堆硬编码的值。这个想法只是生成布局,以便向您展示一般原则。但我相信你可以看到如何适应你自己的情况:

let config = UICollectionViewCompositionalLayoutConfiguration()
config.scrollDirection = .vertical
let inter = 5 as CGFloat
config.interSectionSpacing = 5
let layout = UICollectionViewCompositionalLayout(sectionProvider: { ix, environment in
    let side = 30 as CGFloat
    let cellsz = NSCollectionLayoutSize(widthDimension: .absolute(side), heightDimension: .fractionalHeight(1))
    let cell = NSCollectionLayoutItem(layoutSize: cellsz)
    let groupsz = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(side))
    let count = ix+1
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupsz, subitems: [cell])
    group.interItemSpacing = .fixed(inter)
    let sec = NSCollectionLayoutSection(group: group)
    let width = environment.container.contentSize.width
    let inset = (width - CGFloat(count)*side - (CGFloat(count)-1)*inter) / 2.0
    sec.contentInsets = .init(top: 0, leading: inset, bottom: 0, trailing: 0)
    return sec
}, configuration: config)

这可能不是唯一的方法。我认为,您可以改为调用NSCollectionLayoutGroup.custom并手动布置单元格。但我认为这不是一个糟糕的解决方案。

我还应该说,我不相信集合视图是获得您想要达到的结果的最佳方式。您最好自己直接在代码中布置座位视图。


推荐阅读