在哪里突出显示UICollectionViewCell:委托还是单元格?

时间:2013-03-18 17:35:40

标签: ios ios6 uicollectionview uicollectionviewcell

根据Collection View Programming Guide,应该处理UICollectionViewDelegate中单元格高光的视觉状态。像这样:

- (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];
}

我不喜欢这种方法,它为委托添加了非常特定于单元格的逻辑。事实上,UICollectionViewCell通过highlighted属性独立管理其突出显示的状态。

那么不会覆盖setHighlighted:更清洁的解决方案吗?

- (void)setHighlighted:(BOOL)highlighted
{
    [super setHighlighted:highlighted];
    if (highlighted) {
        [self highlight];
    } else {
        [self unhighlight];
    }
}

这种方法有没有缺点而不是委托方法?

7 个答案:

答案 0 :(得分:51)

正如文档所述,您可以在突出显示单元格时依赖highlighted属性进行更改。例如,以下代码将在突出显示时使单元格变为红色(但不是其子视图):

- (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);
    } 
}

如果你添加这样的东西,背景会变成紫色(红色+不透明的蓝色):

- (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;
}

所以你可以同时使用它们(不一定都改变细胞外观)。不同的是,使用委托方法,您还有indexPath。它可能用于创建多选(您将使用此方法与选择委托方法一起),在单元格突出显示时显示一些预览,以显示其他视图的一些动画...这个委托有相当多的设备我认为的方法。

作为一个结论,我会让单元格外观由单元格本身处理,并使用委托方法让控制器在同一时间内制作一些很酷的东西。

答案 1 :(得分:13)

下面概述了两种可能的方法。

单元格子类化

清除方法,如果已经从UICollectionViewCell继承。

class CollectionViewCell: UICollectionViewCell {

    override var highlighted: Bool {
        didSet {
            self.contentView.backgroundColor = highlighted ? UIColor(white: 217.0/255.0, alpha: 1.0) : nil
        }
    }
}

<强> UICollectionViewDelegate

不太干净,需要集合视图委托了解单元格的表示逻辑。

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
    }
}

答案 2 :(得分:6)

嗯......因为所有这些方法都是正确的。我找到了对我来说最简单的方式。只需覆盖setSelected:方法(例如更改背景颜色):

-(void)setSelected:(BOOL)selected{
    self.backgroundColor = selected?[UIColor greenColor]:[UIColor grayColor];
    [super setSelected:selected];
}

......它的工作原理&#34;开箱即用&#34; (即使使用collectionView.allowsMultipleSelection)

答案 3 :(得分:6)

请注意,UICollectionViewCell具有selectedBackgroundView属性。默认情况下,它是零。只需为此属性创建一个视图,它将在用户触摸单元格时显示。

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
}

答案 4 :(得分:4)

足以突出显示单元格(Swift 4)

class MyCollectionViewCell: UICollectionViewCell {
...
    override var isHighlighted: Bool {
        didSet {
            if isHighlighted {
                self.contentView.alpha = 0.6
            }
            else {
                self.contentView.alpha = 1.0
            }
        }
    }
}

答案 5 :(得分:2)

直接从UICollectionViewCell.h获取 - 覆盖setSelectedsetHighlighted都是正确的。根据您的具体情况,您可以考虑将自定义视图分配给backgroundViewselectedBackgroundView,这些视图会在选择时自动交换。

// 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;

答案 6 :(得分:0)

斯威夫特3 :(根据A-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
    }
}