如何使用 Swift 制作简单的集合视图

How to make a simple collection view with Swift

我正在努力学习如何使用 UICollectionViewdocumentation 有点难以理解,我找到的教程要么在 Objective C 中,要么在很长的复杂项目中。

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

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

该项目已通过 Xcode 10 和 Swift 4.2 测试。

创建一个新项目

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

添加代码

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

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" 的值相同

然后在单元格的身份检查器中,将 class 名称设置为 MyCollectionViewCell,我们自定义的 class。

连接插座

  • 将集合单元格中的 Label 挂接到 MyCollectionViewCell class 中的 myLabel。 (你可以Control-drag。)
  • 将集合视图 delegatedataSource 挂接到视图控制器。 (右键单击文档大纲中的集合视图。然后单击加号箭头并将其向上拖动到视图控制器。)

完成

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

进行改进

上面的例子可行,但它很丑陋。这里有一些你可以玩的东西:

背景色

在 Interface Builder 中,转到您的 集合视图 > 属性检查器 > 视图 > 背景

单元格间距

将单元格之间的最小间距更改为较小的值使其看起来更好。在 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 class:

// 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版本

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
}

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

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)
    }

}

对于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
}