UICollectionView-Tutorial: Foto-Grid implementieren
Das Tutorial zeigt anhand eines Foto-Grids, wie mit UICollectionView und UICollectionViewController Darstellungen aus sich wiederholenden Cell-Views erstellt werden können.
Bildrechte:
Verwendung unter Creative Commons Lizenz
Siehe:
Belgien, Frankreich, Deutschland, Griechenland, Österreich
-
Verwende für dieses Tutorial die aktuelle Version von Xcode (dieses Tutorial wurde zuletzt getestet am 27. Oktober 2019 mit Xcode 11.1).
-
Lade den Start-Stand von dem Beispielprojekt Countries. Dieses enthält einige Beispieldaten so dass Du Dich in diesem Tutorial auf die Implementierung des UICollectionViewControllers konzentrieren kannst.
-
Mache Dich mit dem Projekt vertraut: Es gibt unter Model einen Typ Country, der Daten aus einer lokalen JSON-Datei lädt sowie einige Bilder in den Assets des Projektes:
-
Entferne den bestehenden ExampleViewController aus dem Storyboard. Lösche auch die zugehörige Swift-Datei ExampleViewController.
-
Füge in Main.storyboard über die Library einen neuen Collection View Controller ein:
-
Ziehe die Zelle größer - mit gedrückter Shift-Taste kann dabei das quadratische Seitenverhältnis beibehalten werden:
-
Füge in der Zelle ebenfalls über die Library ein Image View ein. Achte darauf, das das Image View innerhalb der Collection View Cell angelegt wird:
-
Erstelle Constraints, die das Image-View auf die Größe der Zelle skalieren:
-
Vergib für die Zelle einen Reuse Identifier, z.B. ImageCell:
-
Setze für den View Controller die Eigenschaft Is Initial View Controller um diesen als Start-Controller für das Storyboard festzulegen:
-
Erstelle per Rechtsklick auf die Gruppe Controller im Project Navigator mit New File eine neue Cocoa Touch Class GalleryCollectionViewController, die von UICollectionViewController erbt.
-
Passe die Konstante mit dem reuseIdentifier entsprechend Deiner Angabe im Storyboard an. Deklariere eine Eigenschaft countries die die Liste aller Länder via Country.allCountries holt.
Achtung: Entferne unbedingt den Aufruf von self.collectionView!.register(...) im viewDidLoad: Dieser Code wird benötigt, um Zellen programmatisch zu erstellen und muss für die Verwendung von Zellen gemäß Storyboard entfernt werden:private let reuseIdentifier = "ImageCell" class GalleryCollectionViewController: UICollectionViewController { var countries = Country.allCountries override func viewDidLoad() { super.viewDidLoad() // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Achtung, entfernen: // self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) // Do any additional setup after loading the view. } // ... }
-
Deklariere oberhalb der GalleryCollectionViewController-Klasse eine neue Klasse GalleryImageCell für die Zelle:
private let reuseIdentifier = "ImageCell" class GalleryImageCell: UICollectionViewCell { } class GalleryCollectionViewController: UICollectionViewController { // ... }
-
Gib die erstellte UICollectionViewController-Klasse im Storyboard als Klasse für die Controller an:
-
Gib die GalleryImageCell-Klasse im Storyboard als Klasse für die Zelle an:
-
Öffne den Assistant Editor:
-
Erstelle eine Outlet-Eigenschaft imageView für das Image View in GalleryImageCell (wenn das nicht klappt, ist entweder die Zell-Klasse nicht korrekt angegeben oder ein Xcode-Neustart notwendig):
-
Implementiere die Methoden des UICollectionViewDataSource-Protokolls so, dass die Zellen gemäß der countries-Daten befüllt werden - die Country-Klasse hat eine Eigenschaft image, mit der das Bild aus den Assets geladen werden kann:
class GalleryCollectionViewController: UICollectionViewController { // ... // MARK: UICollectionViewDataSource override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { // Methode kann alternativ entfallen return 1 } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return countries.count } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! GalleryImageCell let country = countries[indexPath.row] cell.imageView.image = country.image return cell } }
-
Starte die App und teste die Anzeige der Bilder.
-
Optional kann das Layout noch verbessert werden. Setze dazu dem Image View im Storyboard die Eigenschaft Content Mode = Aspect Fill (die Bilder füllen dann den kompletten Platz aus). Setze dem UICollectionView zudem ein UICollectionViewFlowLayout, um die Layout-Parameter anzupassen und implementiere die UIViewController-Methode viewWillTransition(to:, with:), um die Zell-Größe bei der Rotation des Gerätes entsprechend anzupassen:
class GalleryCollectionViewController: UICollectionViewController { // ... override func viewDidLoad() { super.viewDidLoad() let flowLayout = UICollectionViewFlowLayout() flowLayout.minimumInteritemSpacing = 0 flowLayout.minimumLineSpacing = 0 self.collectionView.collectionViewLayout = flowLayout updateLayout(for: self.view.bounds.size) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { updateLayout(for: size) } private func updateLayout(for size: CGSize) { if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { let width = size.width let count = Int(width) / 180 let itemWidth = width / CGFloat(count) flowLayout.itemSize = CGSize(width: itemWidth, height: itemWidth) flowLayout.invalidateLayout() } } // ... }
-
Prüfe das Ergebnis:
Weitere Informationen
-
UICollectionViewControllerDokumentation zur UICollectionViewController-Klasse.
-
WWDC 2018: A Tour of UICollectionViewWWDC-Vortrag zum Thema CollectionView.
-
WWDC 2019: Advances in Collection View LayoutWWDC-Vortrag zu den Neuerungen vom UICollectionView-Layout in iOS 13.