Jak zrobić prosty widok kolekcji za pomocą Swift


181

Próbuję nauczyć się korzystać UICollectionView. Dokumentacja jest trochę trudne do zrozumienia i samouczków, które znalazłem były albo w Objective C lub długo skomplikowanych projektów.

Kiedy uczyłem się, jak korzystać UITableView, My ❤ Swift's, jak zrobić prosty widok tabeli z iOS 8, a Swift miał bardzo podstawową konfigurację i wyjaśnienie, które mnie uruchomiły. Czy jest coś takiego UICollectionView?

Odpowiedź poniżej to moja próba nauczenia się tego.

Odpowiedzi:


500

Ten projekt został przetestowany z Xcode 10 i Swift 4.2.

Utwórz nowy projekt

Może to być tylko aplikacja z pojedynczym widokiem.

Dodaj kod

Utwórz nowy plik Cocoa Touch Class (Plik> Nowy> Plik ...> iOS> Cocoa Touch Class). Nazwij to MyCollectionViewCell. Ta klasa będzie przechowywać wyloty widoków, które dodajesz do komórki w serii ujęć.

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

Podłączymy to gniazdko później.

Otwórz ViewController.swift i upewnij się, że masz następującą treść:

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

Notatki

  • UICollectionViewDataSourcei UICollectionViewDelegatesą protokołami, których przestrzega widok kolekcji. Możesz także dodać UICollectionViewFlowLayoutprotokół, aby programowo zmienić rozmiar widoków, ale nie jest to konieczne.
  • Po prostu umieszczamy proste ciągi w naszej siatce, ale z pewnością możesz zrobić zdjęcia później.

Skonfiguruj scenorys

Przeciągnij widok kolekcji do kontrolera widoku w swojej serii ujęć. Możesz dodać ograniczenia, aby wypełnić widok nadrzędny, jeśli chcesz.

wprowadź opis zdjęcia tutaj

Upewnij się, że domyślne są również ustawienia w Inspektorze atrybutów

  • Pozycje: 1
  • Układ: przepływ

Małe pole w lewym górnym rogu widoku kolekcji to komórka widoku kolekcji. Użyjemy go jako naszej prototypowej komórki. Przeciągnij etykietę do komórki i wyśrodkuj ją. Jeśli chcesz, możesz zmienić rozmiar granic komórki i dodać wiązania, aby wyśrodkować etykietę.

wprowadź opis zdjęcia tutaj

Wpisz „komórkę” (bez cudzysłowów) w polu Identyfikator Inspektora atrybutów dla komórki widoku kolekcji. Zauważ, że jest to ta sama wartość, co let reuseIdentifier = "cell"w ViewController.swift.

wprowadź opis zdjęcia tutaj

A w Inspektorze tożsamości dla komórki ustaw nazwę klasy na MyCollectionViewCellnaszą niestandardową klasę, którą stworzyliśmy.

wprowadź opis zdjęcia tutaj

Podłączyć gniazda

  • Hook etykiecie w komórce do zbierania myLabelwMyCollectionViewCell klasie. (Możesz przeciągnąć z wciśniętym klawiszem Control ).
  • Zaczep widok kolekcji delegatei dataSourcekontroler widoku. (Kliknij prawym przyciskiem myszy Widok kolekcji w konspekcie dokumentu. Następnie kliknij i przeciągnij strzałkę plus w górę do kontrolera widoku.)

wprowadź opis zdjęcia tutaj

Skończone

Oto jak to wygląda po dodaniu wiązań do wyśrodkowania etykiety w komórce i przypięciu widoku kolekcji do ścian elementu nadrzędnego.

wprowadź opis zdjęcia tutaj

Dokonywanie ulepszeń

Powyższy przykład działa, ale jest raczej brzydki. Oto kilka rzeczy, z którymi możesz grać:

Kolor tła

W Konstruktorze interfejsów przejdź do widoku Kolekcja> Inspektor atrybutów> Widok> Tło .

Odstępy między komórkami

Zmiana minimalnego odstępu między komórkami na mniejszą wartość poprawia wygląd. W Konstruktorze interfejsów przejdź do swojego widoku Kolekcja> Inspektor rozmiarów> Minimalne odstępy i zmniejsz wartości. „Dla komórek” to odległość w poziomie, a „Dla linii” to odległość w pionie.

Kształt komórki

Jeśli chcesz mieć zaokrąglone rogi, ramkę itp., Możesz bawić się komórką layer. Oto przykładowy kod. Umieściłbyś to bezpośrednio cell.backgroundColor = UIColor.cyanw powyższym kodzie.

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

Zobacz tę odpowiedź na inne rzeczy, które możesz zrobić z warstwą (na przykład cień).

Zmiana koloru po stuknięciu

Zapewnia lepszą obsługę, gdy komórki reagują wizualnie na stuknięcia. Jednym ze sposobów osiągnięcia tego jest zmiana koloru tła podczas dotykania komórki. Aby to zrobić, dodaj następujące dwie metody do swojej ViewControllerklasy:

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

Oto zaktualizowany wygląd:

wprowadź opis zdjęcia tutaj

Dalsze badanie

Wersja UITableView tego pytania i odpowiedzi


1
dostaję cell.myLabel jako zero i zawiesza się. jakiś pomysł dlaczego? Używam niestandardowego układu
Gerald

4
Jeśli nie podłączysz gniazdka poprzez przeciągnięcie z kontrolki w serii ujęć do kodu „ @IBOutletfor myLabelin”, nastąpi awaria.
Suragch,

3
jeśli używasz konstruktora interfejsów i odwołujesz się do komórki za pomocą gniazdka, nie rejestruj niestandardowej klasy komórek w kontrolerze. zobacz to
Gerald

1
jeśli wylot UICollectionViewCell jest zerowy, musisz go usunąć self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell"). Jeśli nadal masz problem, sprawdź, czy reuseIdentifierjest ona taka sama dequeueReusableCellWithReuseIdentifierw scenorysie
Ashok R

40
Chciałbym, aby dokumentacja Apple była tak łatwa do odczytania, jak to wyjaśnienie
elmarko,

3

Delegaci i źródła danych 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

Dla 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

Implementacja UICollectionView jest dość interesująca. Możesz użyć prostego kodu źródłowego i obejrzeć samouczek wideo, korzystając z tych łączy:

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 jest taki sam jak UITableView, ale daje nam dodatkową funkcjonalność polegającą na utworzeniu widoku siatki, co jest nieco problematyczne w UITableView. To będzie bardzo długi post. Wspominam o linku, z którego uzyskasz wszystko w prostych krokach.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.