Je travaille sur UICollectionView
avec une disposition personnalisée. En deux jours, je ne comprends pas comment ajouter un en-tête à UICollectionView
. J'ai un contrôleur de vue très simple (créé dans le storyboard avec une disposition personnalisée):
class ACollectionViewController: UICollectionViewController {
enum Identifiers: String {
case CellIdentifier = "Cell"
case HeaderIdentifier = "Header"
}
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: Identifiers.HeaderIdentifier.rawValue)
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.CellIdentifier.rawValue, forIndexPath: indexPath) as Cell
cell.backgroundColor = UIColor.redColor()
return cell
}
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
println("ip = \(indexPath.item)")
var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView
supplementaryView.backgroundColor = UIColor.blueColor()
return supplementaryView
}
Et voici ma mise en page personnalisée:
class ALayout: UICollectionViewLayout {
override func prepareLayout() {
super.prepareLayout()
}
override func collectionViewContentSize() -> CGSize {
return self.collectionView!.bounds.size
}
let itemWidth = 40
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
let x: Float = Float(10) * Float(indexPath.item)
let y: Float = Float(indexPath.item * itemWidth)
attributes.frame = CGRect(x: CGFloat(x), y: CGFloat(y), width: CGFloat(itemWidth), height: CGFloat(itemWidth))
return attributes
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
var attributes = [UICollectionViewLayoutAttributes]()
let sectionsCount = self.collectionView!.dataSource!.numberOfSectionsInCollectionView!(self.collectionView!)
for section in 0..<sectionsCount {
/// add header
attributes.append(self.layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, atIndexPath: NSIndexPath(forItem: 0, inSection: section)))
let itemsCount = self.collectionView!.numberOfItemsInSection(section)
for item in 0..<itemsCount {
let indexPath = NSIndexPath(forItem: item, inSection: section)
attributes.append(self.layoutAttributesForItemAtIndexPath(indexPath))
}
}
return attributes
}
override func layoutAttributesForSupplementaryViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
var attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, withIndexPath: indexPath)
attributes.frame = CGRect(x: 0, y: 0, width: 320, height: 50)
return attributes
}
}
Le problème est que je ne comprends pas comment ajouter correctement un en-tête de section, ce que devrait être indexPath de cet en-tête. Il y a le commentaire dans le code où l'en-tête est ajouté. L'application se bloque au début avec une erreur
2014-10-21 13:06:22.793 UICollectionViewLayout-Demo[3805:95924] *** Terminating app due to
uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of
kind: UICollectionElementKindCell with identifier Header - must register a nib or a class for
the identifier or connect a prototype cell in a storyboard'
Et je comprends, c'est parce que la cellule a le même indexPath que l'en-tête de section que j'essaie d'ajouter, mais que devrait être indexPath de l'en-tête? Ou peut-être que je le fais totalement faux?
Merci d'avance.
Votre crash se produit parce que vous utilisez
var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView
pour essayer de retirer de la file d'attente l'en-tête et le pied de page (dans collectionView:viewForSupplementaryElementOfKind
). En le changeant en
var supplementaryView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier:Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView
devrait se débarrasser du crash, de sorte que vous pouvez étudier le chemin indexPath. Mais sur mon test, indexPath est toujours juste "0".
Vous utilisez une fonction incorrecte pour l'en-tête. Selon la documentation Apple, utilisez les éléments suivants pour l'en-tête et le pied de page:
func dequeueReusableSupplementaryViewOfKind(_ elementKind: String,
withReuseIdentifier identifier: String,
forIndexPath indexPath: NSIndexPath!) -> AnyObject
au lieu de:
var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView
Au lieu de var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView
Devrait être
let supplementaryView = collectionView.dequeueReusableSupplementaryViewOfKind(kind withReuseIdentifier:Identifiers.HeaderIdentifier.rawValue, forIndexPath:indexPath)