如何在 Swift 的 UIViewController 中添加多个集合视图?

Posted

技术标签:

【中文标题】如何在 Swift 的 UIViewController 中添加多个集合视图?【英文标题】:How can I add multiple collection views in a UIViewController in Swift? 【发布时间】:2015-04-29 06:45:59 【问题描述】:

我尝试了很多天才意识到这一点:

我想在我的 UIViewController 中添加两个不同的 CollectionView。 例如我想把图像放在这些 collectionView 每个 CollectionView 使用自己的图像。 这可能吗?

如果有人能帮我一把,我会很高兴。 :)

【问题讨论】:

【参考方案1】:

是的——这是完全可能的。您可以将它们各自的 UICollectionViewDelegates/UICollectionViewDataSources 分配给不同的类或将 CollectionViews 子类化,将委托和数据源都分配给您当前的 viewController 并在委托方法中向下转换您对 collectionView 的引用,如下所示:

@IBOutlet collectionViewA: CustomCollectionViewA!
@IBOutlet collectionViewB: CustomCollectionViewB!


func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 

    if let a = collectionView as? CustomCollectionViewA 
        return a.dequeueReusableCellWithIdentifier("reuseIdentifierA", forIndexPath: indexPath)
     else 
        return collectionView.dequeueReusableCellWithIdentifier("reuseIdentifierB", forIndexPath: indexPath)    
    

像这样子类 UICollectionView:

class CustomCollectionViewA: UICollectionView 
    // add more subclass code as needed


class CustomCollectionViewB: UICollectionView 
    // add more subclass code as needed

【讨论】:

“子类化 CollectionViews”是什么意思?我没能做到你所说的。【参考方案2】:

这是可能的,您只需将每个 UICollectionView 添加为子视图,并将委托和数据源设置为您的 UIViewController。

这是一个简单的例子。假设您有一个 UICollectionView 工作,您应该能够根据自己的用途调整此代码,以便相当容易地添加第二个:

let collectionViewA = UICollectionView()
let collectionViewB = UICollectionView()
let collectionViewAIdentifier = "CollectionViewACell"
let collectionViewBIdentifier = "CollectionViewBCell"

override func viewDidLoad() 
    // Initialize the collection views, set the desired frames
    collectionViewA.delegate = self
    collectionViewB.delegate = self

    collectionViewA.dataSource = self
    collectionViewB.dataSource = self

    self.view.addSubview(collectionViewA)
    self.view.addSubview(collectionViewB)

在 cellForItemAtIndexPath 委托函数中:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
    if collectionView == self.collectionViewA 
        let cellA = collectionView.dequeueReusableCellWithReuseIdentifier(collectionViewAIdentifier) as UICollectionViewCell

        // Set up cell
        return cellA
    

    else 
        let cellB = collectionView.dequeueReusableCellWithReuseIdentifier(collectionViewBIdentifier) as UICollectionViewCell

        // ...Set up cell

        return cellB
    

在numberOfItemsInSection函数中:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    if collectionView == self.collectionViewA 
        return 0 // Replace with count of your data for collectionViewA
    

    return 0 // Replace with count of your data for collectionViewB

【讨论】:

我在这一行“let collectionViewA = UICollectionView()”上收到此错误“UICollectionView 必须使用非零布局参数初始化” 这对我不起作用!我收到此错误:*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“必须使用非零布局参数初始化 UICollectionView” 我认为“if collectionView == self.collectionViewA”这个比较太重了(你可能会在其他代码中继承这个习惯,这很糟糕)。我建议使用标签属性。这基本上是它的目的 我收到一条错误消息,指出“预期返回 'UICollectionViewCell' 的函数中缺少返回值”。我在 if 和 else 块中使用了两个 return 语句。 @Neck 更新了答案。这将起作用。只需在 if-else 块后添加“return UICollectionView()”【参考方案3】:

您还可以以不同的方式命名集合视图出口(无需子类化):

@IBOutlet weak var collectionView: UICollectionView!

@IBOutlet weak var SecondCollectioView: UICollectionView!

方法:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCell", for: indexPath) as UICollectionViewCell

    if(collectionView == self.SecondCollectioView) 
        cell.backgroundColor = UIColor.black
     else 
         cell.backgroundColor = self.randomColor()
    

    return cell;

这将是另一种方式。

【讨论】:

【参考方案4】:

您可以使用工厂设计模式构建两个不同的集合视图并通过函数返回它们。这是我的 swift 4 工作版本。

此代码位于单独的帮助文件中:

import UIKit

class collectionViews 

static func collectionViewOne() -> UICollectionView 

    let layout = UICollectionViewFlowLayout()
    let collectionViewOne = UICollectionView(frame: CGRect(x: 0, y: 20, width: 200, height: 100), collectionViewLayout: layout)
    return collectionViewOne



static func collectionViewTwo() -> UICollectionView 

    let layout = UICollectionViewFlowLayout()
    let collectionViewTwo = UICollectionView(frame: CGRect(x: 0, y: 300, width: 200, height: 100), collectionViewLayout: layout)
    return collectionViewTwo





这是视图控制器代码:

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate 


let collectionViewOne = collectionViews.collectionViewOne()
let collectionViewTwo = collectionViews.collectionViewTwo()

var myArray = ["1", "2"]
var myArray2 = ["3", "4"]

override func viewDidLoad() 
    super.viewDidLoad()


    collectionViewOne.delegate = self
    collectionViewOne.dataSource = self
    collectionViewOne.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
    view.addSubview(collectionViewOne)


    collectionViewTwo.delegate = self
    collectionViewTwo.dataSource = self
    collectionViewTwo.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell2")
    view.addSubview(collectionViewTwo)



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

    if collectionView == self.collectionViewOne 
        return myArray.count
     else 
        return myArray2.count
    



func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

    if collectionView == self.collectionViewOne 
        let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath as IndexPath)

        myCell.backgroundColor = UIColor.red

        return myCell

     else 

        let myCell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell2", for: indexPath as IndexPath)

        myCell2.backgroundColor = UIColor.blue

        return myCell2
    





Result

【讨论】:

这个会滚动吗?你能用这个“func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)”吗? 是的,我在我正在开发的应用程序中使用了它,它滚动/选择很好 - 当您实现 didSelectItemAt 时,只需确保使用 if/else 语句为每个应用程序设置正确的操作集合视图。 为什么只显示一项?【参考方案5】:

这是我的 swift 5 和 Xcode 11 的工作版本:

为对应的collectionviews创建 outlets: outlets:

@IBOutlet weak var bgCollectionView: UICollectionView!
@IBOutlet weak var frontCollectionView: UICollectionView!
var arrImages = [String : [UIImage]]()

arrImages 包含类似

override func viewDidLoad() 
        super.viewDidLoad()
    arrImages = [
    "frontImg": [//Front UIImage array],
    "bgImg": [//Background UIImage array]
    ]


 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        if let arrImg = arrImages["bgImg"] 
            return arrImg.count
         else if let arrImg = arrImages["frontImg"]
            return arrImg.count
        
        return 0
    

您可以通过两种方式做到这一点

    使用 CollectionView 出口

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell    
    if collectionView == self.bgCollectionView
            if let arrImg = arrImages["bgImg"]
                cell.imgView.image = arrImg[indexPath.row]
            
        else
            if let arrImg = arrImages["frontImg"]
                cell.imgView.image = arrImg[indexPath.row]
            
        
        return cell
    

    使用 CollectionView 标签: 这里 Background Images collectionview 标签是 1,Front Images collectionview 标签是 2。

    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
        if collectionView == collectionView.viewWithTag(1)
            if let arrImg = arrImages["bgImg"]
                cell.imgView.image = arrImg[indexPath.row]
            
        else
            if let arrImg = arrImages["frontImg"]
                cell.imgView.image = arrImg[indexPath.row]
                
            
            return cell
        
     

请在 CollectionView 中添加标签,如下所示:

谢谢。希望它对你有用!!

【讨论】:

以上是关于如何在 Swift 的 UIViewController 中添加多个集合视图?的主要内容,如果未能解决你的问题,请参考以下文章

swift的数组和字典使用

点击时如何将播放按钮更改为暂停按钮?

Swift 3 中的“模糊引用”错误

如何在 UITabBarController 中加载所有视图?

无法将类型的值转换为UINavigationController swift3

UIViewControl之间的七种传值方式