Je ne parviens pas à essayer de créer plusieurs sections dans la vue Collection avec un en-tête pour chaque section. Je ne connais pas Obj-C et j'ai trouvé une bonne quantité de tutoriels, mais je n'ai pas encore trouvé comment le convertir en Swift.
Toutes mes données sont statiques et tout ce dont j'ai besoin est une sorte de tableau ou de dictionnaire que je peux utiliser pour créer plusieurs sections. J'ai déjà une vue de collection avec 1 section qui fonctionne, donc si vous avez un aperçu ou un code pour plusieurs sections, ce serait utile.
Je sais comment définir plusieurs sections à l'aide de
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return sectionData.count
}
Je pense que la principale chose pour laquelle j’ai besoin d’aide est d’implémenter cette fonction.
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { }
et mettre en place les données!
UICollectionView et UITableView sont presque exactement identiques, donc si vous savez faire plusieurs sections dans un UITableView dans Swift, votre aide est également appréciée.
La fonction cellForItemAtIndexPath
gère le remplissage de chaque section avec des cellules, elle ne gère pas les sections ni les vues supplémentaires et ne constitue donc pas l'élément principal pour lequel vous avez besoin d'aide pour créer des en-têtes de section.
la méthode que vous devez implémenter est viewForSupplementaryElementOfKind
. Sa signature est:
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {}
En supposant que votre collectionView fonctionne correctement pour 1 section (vous avez correctement rempli le corps de votre cellForItemAtIndexPath et votre tableau sectionData reflète correctement le nombre de sections que vous souhaitez afficher), vous devriez pouvoir implémenter les en-têtes de section à l'aide des pointeurs suivants:
Avec les cellules, UICollectionView
prend également en charge les objets de vue "supplémentaires", généralement utilisés pour les en-têtes ou les pieds de page. Ces vues supplémentaires fonctionnent de manière très similaire aux objets UICollectionViewCell
. De la même manière que cellForItemAtIndexPath
traite les cellules, la fonction viewForSupplementaryElementOfKind
gère les vues supplémentaires.
Pour l'implémenter, vous devez d'abord préparer votre ViewController. Commencez par modifier votre objet de présentation afin de refléter une taille d'en-tête appropriée, à laquelle chaque en-tête adhère:
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.headerReferenceSize = CGSize(width: self.view.frame.size.width, height: 30)
REMARQUE: j'utilise UICollectionViewFlowLayout.
Ensuite, si vous ne l'avez pas déjà fait, créez une classe SectionHeader qui définit chaque objet d'en-tête de section afin de pouvoir ensuite inscrire cette classe avec votre objet collectionView comme suit:
collectionView!.registerClass(SectionHeaderView.self, forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "SectionHeaderView");
Ici, les premier et troisième arguments transmis sont identiques à ceux d'un enregistrement de classe UICollectionViewCell, le premier argument de cette méthode est la référence à la classe d'en-tête de section que vous avez créée. Le troisième est l'identifiant de réutilisation pour la vue supplémentaire.
Le deuxième argument est spécifique aux vues supplémentaires, cela définit le type kind de la vue supplémentaire, qui dans ce cas est un en-tête, la chaîne de constante fournie par la classe UICollectionViewFlowLayout UICollectionElementKindSectionHeader
est utilisée pour cela. Si vous avez remarqué les paramètres de la viewForSupplementaryElementOfKind
, ce kind est ensuite passé en tant que paramètre kind: String
.
Remplissez le corps de votre viewForSupplementaryElementOfKind
de la même manière que vous le feriez pour une fonction cellForItemAtIndexPath - Utilisation de la méthode dequeueReusableSupplementaryViewOfKind
pour créer un objet SectionHeader, puis définissez tous les attributs nécessaires (libellés, couleurs, etc.) et renvoyez enfin l'objet en-tête.
J'espère que cela t'aides!!
Points de référence:
Voici le code qui a fonctionné pour moi
créer la cellule d'en-tête. Pour ce faire, j'ai créé une classe de cellule personnalisée et une nib pour effectuer la personnalisation de la cellule dans l'éditeur graphique.
Dans viewDidLoad, ajoutez ce qui suit
self.collectionView?.registerNib(UINib(nibName: "KlosetCollectionHeaderViewCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderCell")
Ensuite, vous ajoutez la fonction de délégué
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> KlosetCollectionHeaderViewCell {
let headerCell = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "HeaderCell", forIndexPath: indexPath) as? KlosetCollectionHeaderViewCell
return headerCell!
}
Cela placera la HeaderCell dans la vue en coupe de PFCollectionView Les contrôles affichés dans la cellule que vous les ajoutez au fichier xib, ainsi que les prises et les actions
Après avoir créé et enregistré un en-tête personnalisé (et/ou des pieds de page), vous pouvez facilement spécifier un en-tête différent (ou des pieds de page pour cette question) pour une section différente. Voici un exemple:
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let section = indexPath.section
switch section {
case 0:
let userHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeHeaderReuseIdentifier, for: indexPath) as! UserHeader
return userHeader
default:
let postHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: sectionSpacingHeaderReuseIdentifier, for: indexPath) as! PostHeader
return postHeader
}
case UICollectionElementKindSectionFooter:
let userFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeFooterReuseIdentifier, for: indexPath) as! UserFooter
return userFooter
default:
return UICollectionReusableView()
}
}
Assurez-vous également de spécifier le nombre correct de sections:
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
Définissez votre UICollectionViewCell qui sera votre vue d'en-tête de type UICollectionElementKindSectionHeader - Dans mon cas, j'ai deux en-têtes - OfferHeaderCell et APRHeaderCell définis comme suit:
verticalCollectionView.register(UINib(nibName: "OfferHeaderCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "OfferHeaderCell")
verticalCollectionView.register(UINib(nibName: "APRHeaderCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "APRHeaderCell")
Allez-y et renvoyez un en-tête pour chaque section, puis définissez la taille de l'en-tête de section sur zéro dans cette fonction UICollectionViewDelegateFlowLayout.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if(section==0) {
return CGSize.zero
} else if (section==1) {
return CGSize(width:collectionView.frame.size.width, height:133)
} else {
return CGSize(width:collectionView.frame.size.width, height:100)
}
}
Il est important de définir viewForSupplementaryElementOfKind pour deux sections différentes, comme ci-dessous:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
var reusableview = UICollectionReusableView()
if (kind == UICollectionElementKindSectionHeader) {
let section = indexPath.section
switch (section) {
case 1:
let firstheader: OfferHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "OfferHeaderCell", for: indexPath) as! OfferHeaderCell
reusableview = firstheader
case 2:
let secondHeader: APRHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "APRHeaderCell", for: indexPath) as! APRHeaderCell
reusableview = secondHeader
default:
return reusableview
}
}
return reusableview
}
Et enfin la source de données,
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (section==2) {
return 2
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = verticalCollectionView.dequeueReusableCell(withReuseIdentifier: "ReviseOfferCell", for: indexPath)
cell.backgroundColor = UIColor.white
return cell
}
Remarque: N'oubliez pas d'ajouter UICollectionFlowLayout comme ci-dessous:
// MARK: UICollectionViewDelegateFlowLayout
extension MakeAnOfferController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item == 0 {
return CGSize(width: self.view.frame.size.width, height: 626.0)
}
return CGSize()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if(section==0) {
return CGSize.zero
} else if (section==1) {
return CGSize(width:collectionView.frame.size.width, height:133)
} else {
return CGSize(width:collectionView.frame.size.width, height:100)
}
}
}
La réponse de @ Tarun a fonctionné un festin pour moi; Il me manquait collectionView(_:layout:referenceSizeForHeaderInSection:)
, ce dont j'avais besoin, car parfois les données à afficher étaient triées et parfois non.
En outre, l'épinglage de l'en-tête de la section en haut de l'écran (comme dans l'affichage du tableau, dans l'application Carnet d'adresses d'Apple) a été réalisé en ajoutant les éléments suivants à viewDidLoad()
dans UICollectionViewController:
if let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.sectionHeadersPinToVisibleBounds = true
}
Solution travaillée pour Swift-3
i) Créer une cellule personnalisée && xib correspondante
class SectionHeaderView: UICollectionViewCell {
static let kReuseIdentifier = "SectionHeaderView"
@IBOutlet weak var invitationsSectionHeader: UILabel!
@IBOutlet weak var numberOfPerson: UILabel!
}
ii) Enregistrer la cellule d'affichage de collection personnalisée pour HeaderView
self.collectionView.register(UINib(nibName: SectionHeaderView.kReuseIdentifier, bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: SectionHeaderView.kReuseIdentifier)
iii) Appelez la fonction de délégué pour rendre la vue d'en-tête personnalisée.
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView: SectionHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: SectionHeaderView.kReuseIdentifier, for: indexPath) as! SectionHeaderView
return headerView
default:
return UICollectionReusableView()
}
}
iv) Mention Hauteur de la vue d'en-tête personnalisée
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width:collectionView.frame.size.width, height:30)
}