如何解决具有多个部分的 UICollectionView
大家好,我需要在 collectionView
中使用水平滚动显示 2 个部分。
在第一部分我需要 10 个单元格,在第二部分我需要 9 个单元格
我已经实现了这种方式,但我不明白为什么当我选择第 2 部分的单元格时,indexPath.item
的值是第 1 部分单元格的值
编辑
如你所见,我的 collectionView 有 2 个部分,设置了这样的单元格。同一行 (0,1 2 3 4 5) 和底行的第 2 部分,并像顶行一样显示项目
我哪里做错了?
private func commonInit() -> Void {
backgroundColor = .clear
let cv = UICollectionView(frame: .zero,collectionViewLayout: UICollectionViewFlowLayout())
cv.backgroundColor = .clear
cv.delegate = self
cv.dataSource = self
cv.isPagingEnabled = true
cv.showsHorizontalScrollIndicator = false
addSubview(cv)
if let layout = cv.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal }
TimeSelectorCell.register(in: cv)
cv.anchor(top: topAnchor,leading: leadingAnchor,bottom: bottomAnchor,trailing: trailingAnchor)
}
func numberOfSections(in collectionView: UICollectionView) -> Int { 2 }
func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
if section == 0 { return 10 }
else { return 9 }
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TimeSelectorCell.cellIdentifier,for: indexPath) as! TimeSelectorCell
return cell
}
func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
print(indexPath.item)
}
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeforItemAt indexPath: IndexPath) -> CGSize {
.init(width: collectionView.frame.width / 4,height: collectionView.frame.height / 2)
}
func collectionView(_ collectionView: UICollectionView,minimumLinespacingForSectionAt section: Int) -> CGFloat { 0 }
func collectionView(_ collectionView: UICollectionView,minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 0 }
解决方法
在这些场景中,你必须使用的是 iOS 13 在 CollectionView 中的组合布局。这里有 2 个教程供您理解 -
- https://www.zealousweb.com/how-to-use-compositional-layout-in-collection-view/
- https://medium.com/better-programming/ios-13-compositional-layouts-in-collectionview-90a574b410b8
- WWDC 视频 - https://developer.apple.com/videos/play/wwdc2019/215/
对于您的情况,我已经调整了第二个教程中的示例
func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
return (section == 0) ? 10 : 9
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TimeSelectorCell.cellIdentifier,for: indexPath) as! TimeSelectorCell
return cell
}
private func commonInit() {
let cv = UICollectionView(frame: view.bounds,collectionViewLayout: createLayoutDiffSection())
cv.autoresizingMask = [.flexibleWidth,.flexibleHeight]
TimeSelectorCell.register(in: cv)
cv.dataSource = self
cv.delegate = self
addSubview(cv)
}
到目前为止,它与您的代码几乎相同。现在 createLayoutDiffSection() 方法是 -
func createLayoutDiffSection() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int,layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let seperateFlow = true
let columns = (sectionIndex == 0) ? 10 : 9
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 0,leading: 2,bottom: 0,trailing: 2)
let groupHeight = NSCollectionLayoutDimension.fractionalWidth(0.2)
let widthFraction:CGFloat = (sectionIndex == 0) ? 1 : 0.9
let groupSizeWidth:CGFloat = seperateFlow ? (widthFraction * 2) : 1
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(groupSizeWidth),heightDimension: groupHeight)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,subitem: item,count: columns)
let section = NSCollectionLayoutSection(group: group)
if seperateFlow {
section.orthogonalScrollingBehavior = .continuous
}
section.contentInsets = NSDirectionalEdgeInsets(top: 20,leading: 0,bottom: 20,trailing: 0)
return section
}
return layout
}
如果两个部分的滚动不是分开的,则设置 -
让seperateFlow = false
这里需要理解的要点是 -
尺寸分类
我们可以根据需要使用四种尺寸选项,这样就无需进行计算即可获得所需的输出。让我们看看所有的尺寸类:
- fractionalWidth():使用fractionalWidth我们可以设置宽度/高度 单元格的宽度与其父级的宽度成正比
- fractionalHeight(): 使用fractionalHeight,我们可以设置单元格的宽度/高度 与其父母的身高成正比
- absolute():使用绝对 值,我们可以将单元格的宽度/高度设置为固定值
- estimate():使用估计值,我们可以设置单元格的宽度/高度 根据内容大小。系统将决定最优 内容的宽度/高度。
核心概念
要构建任何组合布局,需要实现以下四个类:
- NSCollectionLayoutSize — 宽度和高度尺寸是 类型 NSCollectionLayoutDimension 可以通过设置 布局的部分宽度/高度(相对于其的百分比 容器),或通过设置绝对或估计大小。
- NSCollectionLayoutItem — 这是呈现在您的布局的单元格 基于大小的屏幕。
- NSCollectionLayoutGroup — 它以水平、垂直或自定义形式保存 NSCollectionLayoutItem。
- NSCollectionLayoutSection — 这用于通过传递 NSCollectionLayoutGroup 来初始化部分。部分最终构成了组合布局。
func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
if (indexPath.section == 0 )
{
// cell of section 1
print(indexPath.item)
}else{
// cell of section 2
print(indexPath.item)
}
}
你可以试试!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。