Où mettre en évidence UICollectionViewCell: delegate ou cell?
Selon Collection Visualiser Le Guide De Programmation on devrait gérer l'état visuel des points saillants de la cellule dans le UICollectionViewDelegate
. Comme ceci:
- (void)collectionView:(PSUICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
MYCollectionViewCell *cell = (MYCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
[cell highlight];
}
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
MYCollectionViewCell *cell = (MYCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
[cell unhighlight];
}
ce que je n'aime pas dans cette approche, c'est qu'elle ajoute de la logique au délégué qui est très spécifique à la cellule. En fait, UICollectionViewCell
gère son état surligné de manière indépendante, via le highlighted
propriété.
ne Serait pas primordial setHighlighted:
être une solution plus propre, alors?
- (void)setHighlighted:(BOOL)highlighted
{
[super setHighlighted:highlighted];
if (highlighted) {
[self highlight];
} else {
[self unhighlight];
}
}
sont les inconvénients de cette approche au lieu de la déléguer approche?
6 réponses
Que dit la documentation, vous pouvez compter sur highlighted
propriété à changer pendant que la cellule est surlignée. Par exemple, le code suivant rend la cellule rouge lorsqu'elle est surlignée (mais pas ses sous-vues):
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
if (self.highlighted) {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, self.bounds);
}
}
Et si vous ajouter quelque chose comme ça l'arrière-plan deviendra violet (rouge + bleu opaque):
- (void)collectionView:(UICollectionView *)colView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [colView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.5];
}
- (void)collectionView:(UICollectionView *)colView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [colView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = nil;
}
vous pouvez donc utiliser les deux ensemble (pas nécessairement les deux modifiant l'apparence de la cellule). La différence est qu'avec délégué méthodes vous avez aussi indexPath
. Il peut être utilisé pour créer la multi-sélection (vous utiliserez cette méthode en même temps que les méthodes de sélection des délégués), pour afficher un aperçu pendant que la cellule est surlignée, pour afficher une animation avec d'autres vues... Il y a pas mal d'appareils pour ces méthodes de délégué à mon avis.
en conclusion, je laisserais l'apparence de la cellule être manipulée par la cellule elle-même et j'utiliserais des méthodes de délégation pour laisser le contrôleur faire quelque chose de frais dans la même temps.
Deux approches possibles sont décrites ci-dessous.
Cellule Sous-Classement
approche plus propre si déjà subclassing de UICollectionViewCell
.
class CollectionViewCell: UICollectionViewCell {
override var highlighted: Bool {
didSet {
self.contentView.backgroundColor = highlighted ? UIColor(white: 217.0/255.0, alpha: 1.0) : nil
}
}
}
Uicollection Viewdelegate
moins propre, nécessite que le délégué de vue collection soit au courant de la logique de présentation des cellules.
func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) {
cell.contentView.backgroundColor = UIColor(white: 217.0/255.0, alpha: 1.0) // Apple default cell highlight color
}
}
func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) {
cell.contentView.backgroundColor = nil
}
}
Bien...que toutes ces méthodes sont correctes. J'ai trouvé la voie qui semble la plus facile pour moi. Il suffit de surcharger la méthode setSelected: (par exemple pour changer la couleur de fond):
-(void)setSelected:(BOOL)selected{
self.backgroundColor = selected?[UIColor greenColor]:[UIColor grayColor];
[super setSelected:selected];
}
... Il fonctionne "hors de la boîte" (même avec collectionView.allowsMultipleSelection)
Notez que UICollectionViewCell
a un selectedBackgroundView
propriété. Par défaut, c'est nul. Il suffit de créer une vue pour cette propriété, et il apparaîtra lorsque l'utilisateur touche la cellule.
override func awakeFromNib() {
super.awakeFromNib()
let view = UIView(frame: contentView.bounds)
view.isUserInteractionEnabled = false
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.backgroundColor = UIColor(white: 0.94, alpha: 1.0)
selectedBackgroundView = view
}
tel qu'il est tiré directement de Uicollection Viewcell.h-surpasser les deux setSelected
et setHighlighted
sont corrects. Selon votre situation, vous pourriez envisager d'assigner des vues personnalisées à backgroundView
et selectedBackgroundView
qui sont échangés automatiquement lors de la sélection.
// Cells become highlighted when the user touches them.
// The selected state is toggled when the user lifts up from a highlighted cell.
// Override these methods to provide custom UI for a selected or highlighted state.
// The collection view may call the setters inside an animation block.
@property (nonatomic, getter=isSelected) BOOL selected;
@property (nonatomic, getter=isHighlighted) BOOL highlighted;
// The background view is a subview behind all other views.
// If selectedBackgroundView is different than backgroundView, it will be placed above the background view and animated in on selection.
@property (nonatomic, retain) UIView *backgroundView;
@property (nonatomic, retain) UIView *selectedBackgroundView;
Swift 3: (à partir de la réponse d'Un-Live)
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
override var highlighted: Bool {
didSet {
self.setNeedsDisplay()
}
}
override func drawRect(rect: CGRect) {
super.drawRect(rect)
myImageView.highlighted = self.highlighted
}
}
Swift 4
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
override var isHighlighted: Bool {
didSet {
self.setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
super.draw(rect)
myImageView.isHighlighted = self.isHighlighted
}
}