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

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

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

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

【问题讨论】:

    标签: ios swift 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
          }
      

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

      1. 使用 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
          }
      
      1. 使用 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 中添加标签,如下所示:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-07
        • 2011-01-07
        相关资源
        最近更新 更多