iOS
UICollectionView
Recherche…
Créer une vue de collection par programme
Rapide
func createCollectionView() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height), collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
view.addSubview(collectionView)
}
Objectif c
- (void)createCollectionView {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[self.view addSubview:collectionView];
}
Swift - UICollectionViewDelegateFlowLayout
// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 50, height: 50)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 5.0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 5.0
}
}
Créer une UICollectionView
Initialiser un UICollectionView
avec un cadre CGRect
:
Rapide:
let collection = UICollectionView(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
Objectif c:
UICollectionView *collection = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 200, 21)];
Vous pouvez également créer un UICollectionView
dans Interface Builder
UICollectionView - Source de données
Chaque vue de collection doit avoir un objet Datasource
. L'objet Datasource
est le contenu que votre application affichera dans UICollectionView
. Au minimum, tous les objets Datasource
doivent implémenter collectionView:numberOfItemsInSection:
et collectionView:cellForItemAtIndexPath:
méthodes.
Méthodes requises
Rapide
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// Return how many items in section
let sectionArray = _data[section]
return sectionArray.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(MyCellID)
// If you use a custom cell class then cast the cell returned, like:
// as! MyCollectionViewCellClass
// or you will have errors when you try to use features of that class.
//Customize your cell here, default UICollectionViewCells do not contain any inherent
//text or image views (like UITableView), but some could be added,
//or a custom UICollectionViewCell sub-class could be used
return cell
}
Objectif c
- (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section {
// Return how many items in section
NSArray *sectionArray = [_data objectAtIndex:section];
return [sectionArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Return a cell
UICollectionViewCell *newCell = [self.collectionView
dequeueReusableCellWithReuseIdentifier:MyCellID
forIndexPath:indexPath];
//Customize your cell here, default UICollectionViewCells do not contain any inherent
//text or image views (like UITableView), but some could be added,
//or a custom UICollectionViewCell sub-class could be used
return newCell;
}
Exemple de base Swift d'une vue de collection
Créer un nouveau projet
Il ne peut s'agir que d'une application à vue unique.
Ajouter le code
Créez un nouveau fichier Cocoa Touch Class (Fichier> Nouveau> Fichier ...> iOS> Classe Cocoa Touch). Nommez-le MyCollectionViewCell
. Cette classe contiendra les sorties pour les vues que vous ajoutez à votre cellule dans le storyboard.
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var myLabel: UILabel!
}
Nous allons connecter cette prise plus tard.
Ouvrez ViewController.swift et assurez-vous d'avoir le contenu suivant:
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, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: 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.yellowColor() // make cell more visible in our example project
return cell
}
// MARK: - UICollectionViewDelegate protocol
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
}
Remarques
-
UICollectionViewDataSource
etUICollectionViewDelegate
sont les protocoles que la vue de collection suit. Vous pouvez également ajouter le protocoleUICollectionViewDelegateFlowLayout
pour modifier la taille des vues par programmation, mais cela n'est pas nécessaire. - Nous mettons simplement des chaînes simples dans notre grille, mais vous pouvez certainement faire des images plus tard.
Configurer le storyboard
Faites glisser une vue de collection vers le contrôleur de vue de votre storyboard. Vous pouvez ajouter des contraintes pour le faire remplir la vue parent si vous le souhaitez.
Assurez-vous que vos valeurs par défaut dans l'inspecteur d'attributs sont également
- Articles: 1
- Mise en page: flux
La petite case en haut à gauche de la vue Collection est une cellule de vue de collection. Nous allons l'utiliser comme cellule prototype. Faites glisser une étiquette dans la cellule et centrez-la. Vous pouvez redimensionner les bordures de la cellule et ajouter des contraintes pour centrer l'étiquette si vous le souhaitez.
Ecrivez "cellule" (sans guillemets) dans la zone Identifiant de l'inspecteur d'attributs pour la cellule de vue de collection. Notez que c'est la même valeur que let reuseIdentifier = "cell"
dans ViewController.swift.
Et dans l'inspecteur d'identité pour la cellule, définissez le nom de la classe sur MyCollectionViewCell
, notre classe personnalisée que nous avons MyCollectionViewCell
.
Brancher les sorties
- Accrochez l'étiquette dans la cellule de collection à
myLabel
dans la classeMyCollectionViewCell
. (Vous pouvez faire glisser le curseur .) - Accrochez le
delegate
et ledataSource
du View View au View Controller. (Cliquez avec le bouton droit de la souris sur la vue Collection dans la structure du document. Cliquez ensuite sur la flèche et faites-la glisser jusqu'au View Controller.)
Fini
Voici à quoi cela ressemble après l'ajout de contraintes pour centrer l'étiquette dans la cellule et épingler la vue de collection aux murs du parent.
Faire des améliorations
Si vous souhaitez apporter des améliorations à l'apparence, reportez-vous à la publication d'origine de cet exemple .
Une étude plus approfondie
- Un didacticiel UICollectionView simple
- Partie 1 du didacticiel UICollectionView: Mise en route
- UICollectionView Tutorial Partie 2: Vues réutilisables et sélection de cellules
Effectuer des mises à jour par lots
Vous pouvez animer des modifications complexes dans votre vue de collection à l'aide de la méthode performBatchUpdates
. A l'intérieur du bloc de mise à jour, vous pouvez spécifier plusieurs modifications pour les animer en une seule fois.
collecitonView.performBatchUpdates({
// Perform updates
}, nil)
Dans le bloc de mise à jour, vous pouvez effectuer des insertions, des suppressions, des déplacements et des rechargements. Voici comment déterminer quel indexPath utiliser:
Type | NSIndexPath |
---|---|
Insertion | Index dans un nouveau tableau |
Effacement | Index dans l'ancien tableau |
Bouge toi | de: ancien tableau, à: nouveau tableau |
Recharger | soit nouveau ou ancien tableau (cela ne devrait pas avoir d'importance) |
Vous ne devez appeler que le rechargement sur les cellules qui n'ont pas été déplacées, mais leur contenu a changé. Il est important de noter qu'un déplacement ne rafraîchit pas le contenu d'une cellule, mais déplace uniquement son emplacement.
Pour vérifier que votre mise à jour par lots sera effectuée correctement, assurez-vous que l'ensemble d'indexPaths pour la deletion
, le move-from
et le reload
est unique et que l'ensemble d'indexPaths pour l' insertion
, le move-to
et le reload
est unique.
Voici un exemple de mise à jour de lot correcte:
let from = [1, 2, 3, 4, 5]
let to = [1, 3, 6, 4, 5]
collecitonView.performBatchUpdates({
collectionView.insertItemsAtIndexPaths([NSIndexPath(forItem: 2, inSection: 0)])
collectionView.deleteItemsAtIndexPaths([NSIndexPath(forItem: 1, inSection: 0)])
collectionView.moveItemAtIndexPath(NSIndexPath(forItem: 2, inSection: 0),
toIndexPath: NSIndexPath(forItem: 1, inSection:0))
}, nil)
Configuration de UICollectionViewDelegate et sélection des éléments
Parfois, si une action doit être liée à la sélection de cellules d'une vue de collection, vous devez implémenter le protocole UICollectionViewDelegate
.
Supposons que la vue de collection se trouve dans un UIViewController MyViewController
.
Objectif c
Dans votre MyViewController.h déclare qu'il implémente le protocole UICollectionViewDelegate
, comme ci-dessous
@interface MyViewController : UIViewController <UICollectionViewDelegate, .../* previous existing delegate, as UICollectionDataSource *>
Rapide
Dans votre MyViewController.swift, ajoutez ce qui suit
class MyViewController : UICollectionViewDelegate {
}
La méthode à mettre en œuvre est
Objectif c
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
}
Rapide
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
}
À titre d'exemple, nous pouvons définir la couleur d'arrière-plan de la cellule sélectionnée sur verte.
Objectif c
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor greenColor];
}
Rapide
class MyViewController : UICollectionViewDelegate {
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
var cell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)!
cell.backgroundColor = UIColor.greenColor()
}
}
Gérer plusieurs vues de collection avec DataSource et Flowlayout
Ici, nous gérons plusieurs méthodes de délégation de collections avec des événements de Didselect.
extension ProductsVC: UICollectionViewDelegate, UICollectionViewDataSource{
// MARK: - UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard collectionView == collectionCategory else {
return arrOfProducts.count
}
return arrOfCategory.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard collectionView == collectionProduct else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCategoryCell", for: indexPath) as! ProductCategoryCell
cell.viewBackground.layer.borderWidth = 0.5
//Do some thing as per use
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ProductCell
cell.contentView.layer.borderWidth = 0.5
cell.contentView.layer.borderColor = UIColor.black.cgColor
let json = arrOfProducts[indexPath.row]
//Do something as per use
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard collectionView == collectionCategory else {
let json = arrOfProducts[indexPath.row]
// Do something for collectionProduct here
return
}
let json = arrOfCategory[indexPath.row] as [String: AnyObject]
let id = json["cId"] as? String ?? ""
// Do something
}
}
extension ProductsVC: UICollectionViewDelegateFlowLayout{
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionWidth = collectionView.bounds.width
guard collectionView == collectionProduct else {
var itemWidth = collectionWidth / 4 - 1;
if(UI_USER_INTERFACE_IDIOM() == .pad) {
itemWidth = collectionWidth / 4 - 1;
}
return CGSize(width: itemWidth, height: 50)
}
var itemWidth = collectionWidth / 2 - 1;
if(UI_USER_INTERFACE_IDIOM() == .pad) {
itemWidth = collectionWidth / 4 - 1;
}
return CGSize(width: itemWidth, height: 250);
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
}