ios - 如何使用集合视图组合布局使集合视图内的单元格居中
问题描述
我有以下工作任务:我需要实现电影院视图,其中有一个屏幕和一组座位,每行代表一个部分:
数据来自代表座位的二维数组:
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:
来计算这个,所以任何想法都会非常感激!
解决方案
让每一行,或至少每组具有相同数量项目的行,成为它自己的部分,并为布局提供部分提供程序功能。节提供者函数被赋予节号以及环境对象。从该环境对象中,您可以了解集合视图的宽度。现在只需给组或部分适当的插图。
为了说明,我能够实现这样的布局(三个部分,每个部分的项目数是部分索引加一):
我不会让你悬而未决;我将向您展示该布局的代码。它不漂亮;我使用了一堆硬编码的值。这个想法只是生成布局,以便向您展示一般原则。但我相信你可以看到如何适应你自己的情况:
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
并手动布置单元格。但我认为这不是一个糟糕的解决方案。
我还应该说,我不相信集合视图是获得您想要达到的结果的最佳方式。您最好自己直接在代码中布置座位视图。
推荐阅读
- java - 接收 TXT 文件以读取和存储它们的构造函数
- javascript - Moment.js .toDate() 返回比预期结果晚一年
- javascript - 使用 javascript 和 django 更改 img src 的最佳方法是什么?
- ruby-on-rails - 无法使用 Tailwindcss 和 Webpacker 将 Rails 部署到 Elastic Beanstalk
- r - 如何更改semantic.dashboard 中的主题?
- reactjs - WPGraphQL useMutation GraphQL 错误:“RootMutation”类型的字段“registerUser”上的未知参数“用户名”
- c# - 选择和取消选择游戏对象以更改材质
- sql - 使用汇总按查询分组
- javascript - ReactJS 从状态中删除项目(对象数组)
- spring - Zuul Gateway 服务无法转发到 Eureka 服务器注册的微服务