Cómo hacer una vista de colección simple con Swift


182

Estoy tratando de aprender a usar UICollectionView. La documentación es un poco difícil de entender y los tutoriales que encontré estaban en el Objetivo C o en proyectos largos y complicados.

Cuando estaba aprendiendo a usar UITableView, ❤ Swift's Cómo hacer una vista de tabla simple con iOS 8 y Swift tenía una configuración muy básica y una explicación para ponerme en marcha. ¿Hay algo así para esto UICollectionView?

La respuesta a continuación es mi intento de aprender a hacer esto.

Respuestas:


501

Este proyecto ha sido probado con Xcode 10 y Swift 4.2.

Crea un nuevo proyecto

Puede ser solo una aplicación de vista única.

Agrega el código

Cree un nuevo archivo de Cocoa Touch Class (Archivo> Nuevo> Archivo ...> iOS> Cocoa Touch Class). Nómbralo MyCollectionViewCell. Esta clase mantendrá las salidas para las vistas que agregue a su celda en el guión gráfico.

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

Conectaremos esta salida más tarde.

Abra ViewController.swift y asegúrese de tener el siguiente contenido:

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.item]
        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)!")
    }
}

Notas

  • UICollectionViewDataSourcey UICollectionViewDelegateson los protocolos que sigue la vista de recopilación. También puede agregar el UICollectionViewFlowLayoutprotocolo para cambiar el tamaño de las vistas mediante programación, pero no es necesario.
  • Solo estamos poniendo cadenas simples en nuestra cuadrícula, pero ciertamente podría hacer imágenes más tarde.

Configurar el guión gráfico

Arrastre una Vista de colección al Controlador de vista en su guión gráfico. Puede agregar restricciones para que llene la vista principal si lo desea.

ingrese la descripción de la imagen aquí

Asegúrese de que sus valores predeterminados en el Inspector de atributos también

  • Artículos: 1
  • Diseño: flujo

El pequeño cuadro en la parte superior izquierda de la Vista de colección es una Celda de Vista de colección. Lo usaremos como nuestra célula prototipo. Arrastre una etiqueta a la celda y céntrela. Puede cambiar el tamaño de los bordes de las celdas y agregar restricciones para centrar la etiqueta si lo desea.

ingrese la descripción de la imagen aquí

Escriba "celda" (sin comillas) en el cuadro Identificador del Inspector de atributos para la Celda de vista de colección. Tenga en cuenta que este es el mismo valor que let reuseIdentifier = "cell"en ViewController.swift.

ingrese la descripción de la imagen aquí

Y en el Inspector de identidad de la celda, establezca el nombre de la clase en MyCollectionViewCellnuestra clase personalizada que creamos.

ingrese la descripción de la imagen aquí

Conecta los enchufes

  • Enganche la etiqueta en la celda de colección a myLabella MyCollectionViewCellclase. (Puede Control-arrastrar ).
  • Enganche la Vista de colección delegatey dataSourceal Controlador de vista. (Haga clic con el botón derecho en Vista de colección en el esquema del documento. Luego haga clic y arrastre la flecha más hacia arriba hasta el Controlador de vista).

ingrese la descripción de la imagen aquí

Terminado

Esto es lo que parece después de agregar restricciones para centrar la etiqueta en la celda y fijar la vista de colección a las paredes del elemento primario.

ingrese la descripción de la imagen aquí

Haciendo mejoras

El ejemplo anterior funciona pero es bastante feo. Aquí hay algunas cosas con las que puedes jugar:

Color de fondo

En el Creador de interfaces, vaya a la Vista de colección> Inspector de atributos> Vista> Fondo .

Espaciamiento celular

Cambiar el espacio mínimo entre celdas a un valor más pequeño hace que se vea mejor. En el Creador de interfaces, vaya a la Vista de colección> Inspector de tamaño> Espaciado mínimo y reduzca los valores. "Para celdas" es la distancia horizontal y "Para líneas" es la distancia vertical.

Forma de la celda

Si desea esquinas redondeadas, un borde y similares, puede jugar con la celda layer. Aquí hay un código de muestra. Lo pondría directamente después cell.backgroundColor = UIColor.cyanen el código anterior.

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

Vea esta respuesta para otras cosas que puede hacer con la capa (sombra, por ejemplo).

Cambiar el color cuando se toca

Mejora la experiencia del usuario cuando las celdas responden visualmente a los grifos. Una forma de lograr esto es cambiar el color de fondo mientras se toca la celda. Para hacer eso, agregue los siguientes dos métodos a su ViewControllerclase:

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

Aquí está el aspecto actualizado:

ingrese la descripción de la imagen aquí

Estudio adicional

Versión UITableView de estas preguntas y respuestas


1
estoy obteniendo cell.myLabel como nulo y se está bloqueando. alguna idea de por qué? Estoy usando un diseño personalizado
Gerald

44
Si no conectó la salida arrastrando el control desde la etiqueta en el guión gráfico hasta el código @IBOutletfor myLabel, obtendrá un bloqueo como este.
Suragch

3
Si está utilizando el generador de interfaces y hace referencia a la celda usando una salida, no registre la clase de celda personalizada en su controlador. mira esto
Gerald

1
si la salida UICollectionViewCell es nula, entonces debe eliminarla self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell"). Si todavía tiene el problema, verifique si el reuseIdentifiermismo es dequeueReusableCellWithReuseIdentifiery en el guión gráfico
Ashok R

40
Desearía que la documentación de Apple fuera tan fácil de leer como esta explicación
elmarko el

3

Delegados y fuentes de datos de 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
}

3

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

1

La implementación de UICollectionView es bastante interesante. Puede usar el código fuente simple y ver un video tutorial usando estos enlaces:

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

}

0

UICollectionView es igual a UITableView pero nos brinda la funcionalidad adicional de simplemente crear una vista de cuadrícula, lo cual es un poco problemático en UITableView. Será una publicación muy larga. Menciono un enlace desde donde obtendrás todo en pasos simples.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.