微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

具有多个部分的 UICollectionView

如何解决具有多个部分的 UICollectionView

大家好,我需要在 collectionView 中使用水平滚动显示 2 个部分。

在第一部分我需要 10 个单元格,在第二部分我需要 9 个单元格

我已经实现了这种方式,但我不明白为什么当我选择第 2 部分的单元格时,indexPath.item 的值是第 1 部分单元格的值

编辑

enter image description here

如你所见,我的 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 个教程供您理解 -

  1. https://www.zealousweb.com/how-to-use-compositional-layout-in-collection-view/
  2. https://medium.com/better-programming/ios-13-compositional-layouts-in-collectionview-90a574b410b8
  3. 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

这里需要理解的要点是 -

尺寸分类

我们可以根据需要使用四种尺寸选项,这样就无需进行计算即可获得所需的输出。让我们看看所有的尺寸类:

  1. fractionalWidth():使用fractionalWidth我们可以设置宽度/高度 单元格的宽度与其父级的宽度成正比
  2. fractionalHeight(): 使用fractionalHeight,我们可以设置单元格的宽度/高度 与其父母的身高成正比
  3. absolute():使用绝对 值,我们可以将单元格的宽度/高度设置为固定值
  4. estimate():使用估计值,我们可以设置单元格的宽度/高度 根据内容大小。系统将决定最优 内容的宽度/高度。

核心概念

要构建任何组合布局,需要实现以下四个类:

  1. NSCollectionLayoutSize — 宽度和高度尺寸是 类型 NSCollectionLayoutDimension 可以通过设置 布局的部分宽度/高度(相对于其的百分比 容器),或通过设置绝对或估计大小。
  2. NSCollectionLayoutItem — 这是呈现在您的布局的单元格 基于大小的屏幕。
  3. NSCollectionLayoutGroup — 它以水平、垂直或自定义形式保存 NSCollectionLayoutItem。
  4. 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 举报,一经查实,本站将立刻删除。