Come creare una vista raccolta semplice con Swift


182

Sto cercando di imparare come usare UICollectionView. La documentazione è un po 'difficile da capire e i tutorial che ho trovato erano o nell'Obiettivo C o in progetti lunghi e complicati.

Quando stavo imparando come usare UITableView, We Swift's How to make a tableview semplice con iOS 8 e Swift aveva una configurazione e una spiegazione molto basilari per iniziare. C'è qualcosa di simile per questo UICollectionView?

La risposta di seguito è il mio tentativo di imparare a farlo.

Risposte:


501

Questo progetto è stato testato con Xcode 10 e Swift 4.2.

Crea un nuovo progetto

Può essere solo un'app a visualizzazione singola.

Aggiungi il codice

Crea un nuovo file Cocoa Touch Class (File> Nuovo> File ...> iOS> Cocoa Touch Class). Dillo MyCollectionViewCell. Questa classe conterrà gli sbocchi per le visualizzazioni che aggiungi alla tua cella nello storyboard.

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

Collegheremo questa presa più tardi.

Apri ViewController.swift e assicurati di avere il seguente contenuto:

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

Appunti

  • UICollectionViewDataSourcee UICollectionViewDelegatesono i protocolli che segue la vista della raccolta. È inoltre possibile aggiungere il UICollectionViewFlowLayoutprotocollo per modificare le dimensioni delle visualizzazioni a livello di codice, ma non è necessario.
  • Stiamo semplicemente inserendo semplici stringhe nella nostra griglia, ma potresti sicuramente fare immagini in seguito.

Imposta lo storyboard

Trascina una vista raccolta sul controller di visualizzazione nello storyboard. Se lo desideri, puoi aggiungere vincoli per riempire la vista padre.

inserisci qui la descrizione dell'immagine

Assicurati che anche le impostazioni predefinite nella finestra di ispezione degli attributi lo siano

  • Articoli: 1
  • Layout: flusso

La piccola casella in alto a sinistra nella vista Raccolta è una cella della vista Raccolta. Lo useremo come nostra cellula prototipo. Trascina un'etichetta nella cella e centrala. Puoi ridimensionare i bordi delle celle e aggiungere vincoli per centrare l'etichetta, se lo desideri.

inserisci qui la descrizione dell'immagine

Scrivi "cella" (senza virgolette) nella casella Identificatore della finestra di ispezione degli attributi per la vista della raccolta. Si noti che questo è lo stesso valore let reuseIdentifier = "cell"di ViewController.swift.

inserisci qui la descrizione dell'immagine

E in Identity Inspector per la cella, imposta il nome della classe su MyCollectionViewCell, la nostra classe personalizzata che abbiamo creato.

inserisci qui la descrizione dell'immagine

Agganciare le prese

  • Agganciare l'etichetta nella cella di raccolta myLabelnella MyCollectionViewCellclasse. (Puoi trascinare Control .)
  • Agganciare la vista raccolta delegatee dataSourceal controller vista. (Fare clic con il pulsante destro del mouse su Vista raccolta nella struttura del documento. Quindi fare clic e trascinare la freccia più verso l'alto su Visualizza controller.)

inserisci qui la descrizione dell'immagine

Finito

Ecco come appare dopo aver aggiunto i vincoli per centrare l'etichetta nella cella e appuntare la Vista raccolta ai muri del genitore.

inserisci qui la descrizione dell'immagine

Miglioramenti

L'esempio sopra funziona ma è piuttosto brutto. Ecco alcune cose con cui puoi giocare:

Colore di sfondo

In Interface Builder, vai alla vista Collezione> Impostazioni Attributi> Visualizza> Sfondo .

Spaziatura cellulare

La modifica della spaziatura minima tra le celle su un valore più piccolo la rende migliore. In Interface Builder, vai alla vista Collezione> Impostazioni dimensioni> Spaziatura minima e riduci i valori. "Per celle" è la distanza orizzontale e "Per linee" è la distanza verticale.

Forma cellulare

Se vuoi angoli arrotondati, un bordo e simili, puoi giocare con la cella layer. Ecco qualche codice di esempio. Lo inseriresti direttamente dopo cell.backgroundColor = UIColor.cyannel codice sopra.

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

Vedi questa risposta per altre cose che puoi fare con il livello (ombra, per esempio).

Cambiare colore quando toccato

Offre un'esperienza utente migliore quando le celle rispondono visivamente ai tocchi. Un modo per raggiungere questo obiettivo è cambiare il colore di sfondo mentre la cella viene toccata. Per fare ciò, aggiungi i seguenti due metodi alla tua ViewControllerclasse:

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

Ecco l'aspetto aggiornato:

inserisci qui la descrizione dell'immagine

Ulteriore studio

Versione UITableView di queste domande e risposte


1
sto ottenendo cell.myLabel come zero ed è in crash. qualche idea del perché? Sto usando un layout personalizzato
Gerald

4
Se non si collegasse l'outlet trascinando il controllo dall'etichetta nello storyboard al codice @IBOutletfor myLabelin, si otterrebbe un arresto del genere.
Suragch,

3
se si utilizza il builder di interfacce e si fa riferimento alla cella mediante un outlet, non registrare la classe di celle personalizzata nel controller. vedi questo
Gerald

1
se la presa UICollectionViewCell è nulla, è necessario rimuoverla self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell"). Se il problema persiste, controllare se lo reuseIdentifierstesso è all'interno dequeueReusableCellWithReuseIdentifiere nello storyboard
Ashok R,

40
Vorrei che la documentazione di Apple fosse facile da leggere come questa spiegazione
elmarko,

3

Delegati e origini dati di 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

Per 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

L'implementazione di UICollectionView è piuttosto interessante. Puoi usare il semplice codice sorgente e guardare un tutorial video usando questi link:

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 è uguale a UITableView ma ci offre la funzionalità aggiuntiva di creare semplicemente una vista a griglia, il che è un po 'problematico in UITableView. Sarà un post molto lungo, menzionerò un link da cui otterrai tutto in semplici passaggi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.