在UICollectionViewCell中使用UICollectionView

17

我希望将一个collectionview作为另一个集合视图单元格的一部分,但不知道如何实现。在哪里可以实现单元格collectionview所需的方法?

4个回答

13

Ash Furrow写的一篇文章解释如何将UICollectionView放置在UITableViewCell中。当在UICollectionViewCell中使用它时,基本上是相同的思路。


11

所有东西都是以编程方式完成的。没有故事板。

我在我的UICollectionViewCell中添加了一个UICollectionView。我还展示了如何再次添加一个UICollectionViewCell到已创建的UICollectionView中,以实现这个结果

输入图像描述

import UIKit

class CategoryCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    private let cellId = "cell"

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    let appsCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        return collectionView
    }()

    func setupViews() {
        backgroundColor = .blue

        addSubview(appsCollectionView)

        appsCollectionView.delegate = self
        appsCollectionView.dataSource = self
        appsCollectionView.register(AppCell.self, forCellWithReuseIdentifier: cellId)

        addConstrainstWithFormat("H:|-8-[v0]-8-|", views: appsCollectionView)
        addConstrainstWithFormat("V:|[v0]|", views: appsCollectionView)

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
        return cell
    }
}

class AppCell: UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setupViews(){
        backgroundColor = .red
    }
}

我的UICollectionViewController

import UIKit

class FeaturedAppsController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    let cellId = "cell"

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        collectionView?.backgroundColor = .white
        collectionView?.register(CategoryCell.self, forCellWithReuseIdentifier: cellId)
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(view.frame.width, 150)
    }

}

整个解释可以在“让我们构建这个应用程序”中找到并开发:https://www.youtube.com/watch?v=Ko9oNhlTwH0&list=PL0dzCUj1L5JEXct3-OV6itP7Kz3tRDmma


你是否在声明appsCollectionView时存在保留循环(retain cycle)?你认为最好让它这样声明:let appsCollectionView: UICollectionView = { [weak self] in ....}吗? - christostsang
@christostsang 这不会创建保留循环,因为在collectionView的init中我们没有捕获/保留“self”。 - Fernando Cardenas
我以为你已经在自我封闭的块中设置了collectionView.delegate = self和collectionView.datasource = self! :) 如果是这样,那么在你的意见中,这是否会导致保留循环? - christostsang
1
我不这么认为,因为delegate和datasource被声明为“weak var”。 - Fernando Cardenas
最后一个问题:您认为是创建不同的UICollectionViewController来处理该appsCollectionView更好,还是像现在这样,在单元格内部设置collectionView过程? - christostsang
不应该在继承自UIView的类中添加ViewController,这就是为什么最好使用collectionView而不是ViewController的原因。您可以拥有一个包含其他视图控制器的viewController,但这不仅需要将它们添加到视图中,还需要进行一些其他设置,以便嵌入式视图控制器中的“viewDidLoad、viewWillAppear”等内容能够正常工作。 - Fernando Cardenas

4
这个答案可能有点晚,但它可能对其他人有帮助。这是一个示例,展示了如何在一个UICollectionViewCell中嵌套另一个UICollectionView
首先,我们创建一个mainCollectionView。然后,在此集合的每个单元格中创建和初始化一个新的UICollectionView。此操作最佳放在UICollectionView的以下委托方法中: func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) 例如,在这里我初始化了MainCollectionViewCell,并让MainCollectionViewCell处理创建新UICollectionView的逻辑。
guard let collectionViewCell = cell as? MainCollectionViewCell else { return }

    collectionViewCell.delegate = self

    let dataProvider = ChildCollectionViewDataSource()
    dataProvider.data = data[indexPath.row] as NSArray

    let delegate = ChildCollectionViewDelegate()

    collectionViewCell.initializeCollectionViewWithDataSource(dataProvider, delegate: delegate, forRow: indexPath.row)

    collectionViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0

这是在 MainCollectionViewCell 上创建一个新的 UICollectionView 的初始化程序。
func initializeCollectionViewWithDataSource<D: protocol<UICollectionViewDataSource>,E: protocol<UICollectionViewDelegate>>(dataSource: D, delegate :E, forRow row: Int) {

    self.collectionViewDataSource = dataSource

    self.collectionViewDelegate = delegate

    let flowLayout = UICollectionViewFlowLayout()
    flowLayout.scrollDirection = .Horizontal

    let collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: flowLayout)
    collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseChildCollectionViewCellIdentifier)
    collectionView.backgroundColor = UIColor.whiteColor()
    collectionView.dataSource = self.collectionViewDataSource
    collectionView.delegate = self.collectionViewDelegate
    collectionView.tag = row

    self.addSubview(collectionView)

    self.collectionView = collectionView

    collectionView.reloadData()
}

希望能对您有所帮助!

我在 GitHub 上做了一个示例,演示了如何在 UICollectionViewCell 中使用 UICollectionView

https://github.com/irfanlone/Collection-View-in-a-collection-view-cell


1

使用Storyboard和Swift 5实现CollectionView嵌套CollectionView的最简单解决方案

请参考此链接了解嵌套CollectionView示例

import UIKit
class ParentViewController:UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
//MARK: Declare variable

//MARK: Decalare outlet
@IBOutlet weak var outerCollectionView: UICollectionView!
@IBOutlet weak var pageControl: UIPageControl!
let outerCount = 4

//MARK: Decalare life cycle methods
override func viewDidLoad() {
    super.viewDidLoad()
    pageControl.numberOfPages = outerCount
    
}
//MARK: Collection View delegate methods
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return outerCount
}
//MARK: Collection View datasource methods
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OuterCell", for: indexPath) as! OuterCollectionViewCell
    cell.contentView.backgroundColor = .none
    return cell
    
}
//MARK:- For Display the page number in page controll of collection view Cell
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let visibleRect = CGRect(origin: self.outerCollectionView.contentOffset, size: self.outerCollectionView.bounds.size)
    let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
    if let visibleIndexPath = self.outerCollectionView.indexPathForItem(at: visiblePoint) {
        self.pageControl.currentPage = visibleIndexPath.row
    }
}
}
class OuterCollectionViewCell: UICollectionViewCell ,UICollectionViewDataSource,UICollectionViewDelegate {

@IBOutlet weak var InnerCollectionView: UICollectionView!

override func awakeFromNib() {
    super.awakeFromNib()
    InnerCollectionView.delegate = self
    InnerCollectionView.dataSource = self
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    6
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "InnerCell", for: indexPath) as! InnerCollectionViewCell
    cell.contentView.backgroundColor = .green
    return cell
}


}
class InnerCollectionViewCell: UICollectionViewCell{


}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接