Comment puis-je ajouter une vue d'en-tête/vue de dessus (pas un en-tête de section) en haut d'un UICollectionView
?
Elle doit agir exactement comme la propriété UITableView
de tableHeaderView
.
Il doit donc s'asseoir au-dessus de la première vue d'en-tête de section (avant la section à l'index 0), faire défiler le reste du contenu et interagir avec l'utilisateur.
Le meilleur que j'ai trouvé jusqu'à présent est de créer un XIB spécial (avec MyCollectionReusableView
sous-classe de UICollectionReusableView
en tant que propriétaire du fichier) pour la première vue d'en-tête de section qui est assez grande pour contenir également mes sous-vues dans l'en-tête, c'est une sorte de hack, je pense, et je n'ai pas réussi à détecter les touches.
Je ne sais pas si je peux créer ma sous-classe MyCollectionReusableView
pour autoriser les contacts ou il existe une meilleure méthode.
J'ai mis une vue en haut d'une vue de collection en ajoutant simplement un UIView comme sous-vue de la vue de collection. Il fait défiler vers le haut avec la vue de la collection et il a une interaction utilisateur UIView normale. Cela fonctionne bien si vous n'avez pas d'en-tête de section, mais ne fonctionne pas si vous en avez. Dans cette situation, je ne vois rien de mal à la façon dont vous le faites. Je ne sais pas pourquoi vous ne détectez pas les contacts, ils fonctionnent bien pour moi.
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 320, self.view.frame.size.height) collectionViewLayout:flowlayout];
self.collectionView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);
UIImageView *imagev = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"015.png"]];
imagev.frame = CGRectMake(0, -50, 320, 50);
[self.collectionView addSubview: imagev];
[self.view addSubview: _collectionView];
J'utilise l'attribut contentInset
pour insérer un cadre en haut du UICollectionView
, puis j'y ajoute la vue image, et cela réussit. Je pense qu'il peut agir exactement comme la propriété UITableView
de tableHeaderView
. Qu'est-ce que tu penses?
La meilleure façon d'y parvenir est de créer un en-tête de section pour la première section. Définissez ensuite la propriété UICollectionViewFlowLayout:
@property(nonatomic) BOOL sectionHeadersPinToVisibleBounds
ou Swift
var sectionHeadersPinToVisibleBounds: Bool
à NON (faux pour Swift). Cela garantira que l'en-tête de section défile en continu avec les cellules et ne sera pas épinglé en haut comme le ferait normalement un en-tête de section.
Je pense que la meilleure façon d'accomplir cela est de sous-classer UICollectionViewLayout (UICollectionViewFlowLayout) et d'ajouter les attributs d'en-tête ou de pied de page nécessaires.
Étant donné que tous les éléments, y compris la vue supplémentaire dans la disposition UICollectionView en fonction de sa propriété collectionViewLayout
, c'est le collectionviewlayout
qui décide s'il existe un en-tête (pied de page) ou non.
Utiliser contentInset
est plus facile, mais il peut y avoir un problème lorsque vous souhaitez masquer ou afficher l'en-tête dynamiquement.
J'ai écrit un protocole pour y parvenir, qui pourrait être adopté par n'importe quelle sous-classe de UICollectionViewLayout pour lui donner un en-tête ou un pied de page. Vous pouvez le trouver ici.
L'idée principale est de créer un UICollectionViewLayoutAttributes
pour l'en-tête et de le renvoyer dans layoutAttributesForElements(in rect: CGRect)
si nécessaire, vous devrez modifier tous les autres attributs, tous leurs emplacements doivent être déplacés vers le bas par en-tête hauteur parce que l'en-tête est au-dessus d'eux tous.
J'ai fini par utiliser une extension UICollectionView pour ajouter mon en-tête personnalisé. En utilisant une balise spécifique, je suis capable de simuler la propriété stockée pour identifier mon en-tête personnalisé (tout transparent de l'extérieur). Vous devrez peut-être faire défiler jusqu'à un décalage spécifique si la disposition de l'UICollectionView n'est pas terminée lorsque vous ajoutez votre en-tête personnalisé.
extension UICollectionView {
var currentCustomHeaderView: UIView? {
return self.viewWithTag(CustomCollectionViewHeaderTag)
}
func asssignCustomHeaderView(headerView: UIView, sideMarginInsets: CGFloat = 0) {
guard self.viewWithTag(CustomCollectionViewHeaderTag) == nil else {
return
}
let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
headerView.frame = CGRect(x: sideMarginInsets, y: -height + self.contentInset.top, width: self.frame.width - (2 * sideMarginInsets), height: height)
headerView.tag = CustomCollectionViewHeaderTag
self.addSubview(headerView)
self.contentInset = UIEdgeInsets(top: height, left: self.contentInset.left, bottom: self.contentInset.bottom, right: self.contentInset.right)
}
func removeCustomHeaderView() {
if let customHeaderView = self.viewWithTag(CustomCollectionViewHeaderTag) {
let headerHeight = customHeaderView.frame.height
customHeaderView.removeFromSuperview()
self.contentInset = UIEdgeInsets(top: self.contentInset.top - headerHeight, left: self.contentInset.left, bottom: self.contentInset.bottom, right: self.contentInset.right)
}
}
}
CustomCollectionViewHeaderTag fait référence au numéro de balise que vous donnez à votre en-tête. Assurez-vous qu'il ne s'agit pas de la balise d'une autre vue intégrée à votre UICollectionView.