【问题标题】:How to make a simple collection view with Swift如何使用 Swift 制作简单的集合视图
【发布时间】:2015-10-22 11:41:11
【问题描述】:

我正在尝试学习如何使用UICollectionViewdocumentation 有点难以理解,我发现的教程要么是 Objective C 的,要么是复杂的项目。

当我学习如何使用 UITableView 时,我们❤ Swift 的 How to make a simple tableview with iOS 8 and Swift 有一个非常基本的设置和解释让我开始。 UICollectionView有这样的事情吗?

下面的答案是我学习这样做的尝试。

【问题讨论】:

    标签: ios swift uicollectionview


    【解决方案1】:

    这个项目已经过 Xcode 10 和 Swift 4.2 的测试。

    创建一个新项目

    它可以只是一个单一视图应用程序。

    添加代码

    创建一个新的 Cocoa Touch Class 文件(File > New > File... > iOS > Cocoa Touch Class)。将其命名为MyCollectionViewCell。此类将保存您添加到情节提要中的单元格的视图的出口。

    import UIKit
    class MyCollectionViewCell: UICollectionViewCell {
        
        @IBOutlet weak var myLabel: UILabel!
    }
    

    我们稍后会连接这个插座。

    打开 ViewController.swift 并确保你有以下内容:

    import UIKit
    class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
        
        let reuseIdentifier = "cell" // also enter this string as the cell identifier in the storyboard
        var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"]
        
        
        // MARK: - UICollectionViewDataSource protocol
        
        // tell the collection view how many cells to make
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return self.items.count
        }
        
        // make a cell for each cell index path
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            
            // get a reference to our storyboard cell
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell
            
            // Use the outlet in our custom class to get a reference to the UILabel in the cell
            cell.myLabel.text = self.items[indexPath.row] // The row value is the same as the index of the desired text within the array.
            cell.backgroundColor = UIColor.cyan // make cell more visible in our example project
            
            return cell
        }
        
        // MARK: - UICollectionViewDelegate protocol
        
        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            // handle tap events
            print("You selected cell #\(indexPath.item)!")
        }
    }
    

    备注

    • UICollectionViewDataSourceUICollectionViewDelegate 是集合视图遵循的协议。您还可以添加 UICollectionViewFlowLayout 协议以编程方式更改视图的大小,但这不是必需的。
    • 我们只是在网格中放置简单的字符串,但您当然可以稍后再制作图像。

    设置故事板

    将集合视图拖到情节提要中的视图控制器。如果您愿意,可以添加约束以使其填充父视图。

    确保属性检查器中的默认值也是

    • 项目:1
    • 布局:流程

    集合视图左上角的小框是集合视图单元格。我们将使用它作为我们的原型单元。将标签拖入单元格并将其居中。如果您愿意,您可以调整单元格边框的大小并添加约束以使标签居中。

    在集合视图单元格的属性检查器的标识符框中写入“单元格”(不带引号)。请注意,这与 ViewController.swift 中的 let reuseIdentifier = "cell" 值相同。

    在单元格的 Identity Inspector 中,将类名设置为 MyCollectionViewCell,这是我们创建的自定义类。

    连接插座

    • 将集合单元格中的标签与MyCollectionViewCell 类中的myLabel 挂钩。 (您可以Control-drag。)
    • 将集合视图delegatedataSource 连接到视图控制器。 (右键单击 Document Outline 中的 Collection View。然后单击并向上拖动加号箭头到 View Controller。)

    完成

    这是在添加约束以使标签在单元格中居中并将集合视图固定到父项的墙壁后的样子。

    进行改进

    上面的例子有效,但它相当难看。这里有一些你可以玩的东西:

    背景颜色

    在 Interface Builder 中,转到您的 Collection View > Attributes Inspector > View > Background

    单元格间距

    将单元格之间的最小间距更改为较小的值使其看起来更好。在 Interface Builder 中,转到您的 Collection View > Size Inspector > Min Spacing 并缩小值。 “对于单元格”是水平距离,“对于线条”是垂直距离。

    细胞形状

    如果您想要圆角、边框等,您可以使用单元格layer。这是一些示例代码。您可以将其直接放在上面代码中的cell.backgroundColor = UIColor.cyan 之后。

    cell.layer.borderColor = UIColor.black.cgColor
    cell.layer.borderWidth = 1
    cell.layer.cornerRadius = 8
    

    请参阅this answer 了解您可以对图层执行的其他操作(例如阴影)。

    点击时更改颜色

    当单元格对点击做出视觉响应时,它可以提供更好的用户体验。实现此目的的一种方法是在触摸单元格时更改背景颜色。为此,请将以下两个方法添加到您的 ViewController 类中:

    // change background color when user touches cell
    func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
        let cell = collectionView.cellForItem(at: indexPath)
        cell?.backgroundColor = UIColor.red
    }
    
    // change background color back when user releases touch
    func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
        let cell = collectionView.cellForItem(at: indexPath)
        cell?.backgroundColor = UIColor.cyan
    }
    

    这是更新后的外观:

    进一步研究

    本问答的UITableView版本

    【讨论】:

    • 我将 cell.myLabel 设为 nil 并且它正在崩溃。知道为什么吗?我使用自定义布局
    • 如果您没有通过从情节提要中的标签控制拖动到代码中的myLabel@IBOutlet 来连接插座,您会遇到这样的崩溃。
    • 如果您使用界面生成器并使用插座引用单元格,请不要在控制器中注册自定义单元格类。见this
    • 如果 UICollectionViewCell 出口为零,那么您必须删除 self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell")。如果您仍然有问题,请检查 reuseIdentifierdequeueReusableCellWithReuseIdentifier 和情节提要中是否相同
    • 我希望 Apple 的文档能像这个解释一样易于阅读
    【解决方案2】:

    对于swift 4.2 --

    //MARK: UICollectionViewDataSource
    
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1     //return number of sections in collection view
    }
    
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10    //return number of rows in section
    }
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath as IndexPath)
        configureCell(cell: cell, forItemAtIndexPath: indexPath)
        return cell      //return your cell
    }
    
    func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {
        cell.backgroundColor = UIColor.black
    
    
        //Customise your cell
    
    }
    
    func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        let view =  collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", for: indexPath as IndexPath) as UICollectionReusableView
        return view
    }
    
    //MARK: UICollectionViewDelegate
    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        // When user selects the cell
    }
    
    func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
        // When user deselects the cell
    }
    

    【讨论】:

      【解决方案3】:

      UICollectionView 的委托和数据源

      //MARK: UICollectionViewDataSource
      
      override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
          return 1     //return number of sections in collection view
      }
      
      override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
          return 10    //return number of rows in section
      }
      
      override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
          let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionCell", forIndexPath: indexPath)
          configureCell(cell, forItemAtIndexPath: indexPath)
          return cell      //return your cell
      }
      
      func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {
          cell.backgroundColor = UIColor.blackColor()
      
      
          //Customise your cell
      
      }
      
      override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
          let view =  collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", forIndexPath: indexPath) as UICollectionReusableView
          return view
      }
      
      //MARK: UICollectionViewDelegate
      override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
            // When user selects the cell
      }
      
      override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
           // When user deselects the cell
      }
      

      【讨论】:

        【解决方案4】:

        UICollectionView 的实现非常有趣。 您可以使用简单的源代码并通过这些链接观看视频教程:

        https://github.com/Ady901/Demo02CollectionView.git

        https://www.youtube.com/watch?v=5SrgvZF67Yw

        extension ViewController : UICollectionViewDataSource {
        
            func numberOfSections(in collectionView: UICollectionView) -> Int {
                return 2
            }
        
            func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
                return nameArr.count
            }
        
            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DummyCollectionCell", for: indexPath) as! DummyCollectionCell
                cell.titleLabel.text = nameArr[indexPath.row]
                cell.userImageView.backgroundColor = .blue
                return cell
            }
        
        }
        
        extension ViewController : UICollectionViewDelegate {
        
            func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
                let alert = UIAlertController(title: "Hi", message: "\(nameArr[indexPath.row])", preferredStyle: .alert)
                let action = UIAlertAction(title: "OK", style: .default, handler: nil)
                alert.addAction(action)
                self.present(alert, animated: true, completion: nil)
            }
        
        }
        

        【讨论】:

          【解决方案5】:

          UICollectionView 与 UITableView 相同,但它为我们提供了简单创建网格视图的附加功能,这在 UITableView 中有点问题。这将是一篇很长的帖子,我会提到 link,您可以从那里通过简单的步骤获得所有内容。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-09-14
            • 1970-01-01
            • 2016-05-01
            • 1970-01-01
            • 2015-06-21
            • 1970-01-01
            • 2020-04-16
            • 2017-10-30
            相关资源
            最近更新 更多