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?

31
demandé sur hpique 2013-03-18 21:35:39

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.

49
répondu A-Live 2016-06-15 19:55:37

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
    }
}
11
répondu bizz84 2016-01-13 22:30:14

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)

6
répondu JakubKnejzlik 2014-08-07 10:28:22

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
}
6
répondu Dave Batton 2017-09-08 14:56:09

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;
1
répondu Brody Robertson 2014-10-20 18:46:54

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
    }
}
0
répondu oOEric 2018-04-06 19:37:25