ios 在哪里突出显示 UICollectionViewCell:委托或单元格?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15483229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:46:30  来源:igfitidea点击:

Where to highlight UICollectionViewCell: delegate or cell?

iosios6uicollectionviewuicollectionviewcell

提问by hpique

According to the Collection View Programming Guideone should handle the visual state of the cell highlights in the UICollectionViewDelegate. Like this:

根据集合视图编程指南,应该处理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];
}

What I don't like about this approach is that it adds logic to the delegate that is very specific to the cell. In fact, UICollectionViewCellmanages its highlighted state independently, via the highlightedproperty.

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

Wouldn't overriding setHighlighted:be a cleaner solution, then?

那么,覆盖setHighlighted:不是一个更清洁的解决方案吗?

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

Are there any disadvantages to this approach instead of the delegate approach?

这种方法而不是委托方法有什么缺点吗?

回答by A-Live

As the documentation says, you can rely on highlightedproperty to be changed while the cell is highlighted. For example the following code will make the cell red when highlighted (not its subviews though):

正如文档所说,您可以在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);
    } 
}

And if you addsomething like this the background will become purple (red + opaque blue):

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

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

So you can use both together (not necessarily both changing the cell appearance). The difference is that with delegate methods you also have indexPath. It might be used to create multi-selection (you will use this methods together with selection delegate methods), to show some preview while the cell is highlighted, to show some animation with other views... There's quite a few appliance for this delegate methods in my opinion.

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

As a conclusion, I would leave the cell appearance to be handled by the cell itself and use delegate methods to let controller make something cool in the same time.

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

回答by bizz84

Two possible approaches are outlined below.

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

Cell Subclassing

细胞亚类

Cleaner approach if already subclassing from UICollectionViewCell.

如果已经从UICollectionViewCell.

class CollectionViewCell: UICollectionViewCell {

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

UICollectionViewDelegate

UICollectionViewDelegate

Less clean, requires the collection view delegate to know about the presentation logic of the cells.

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

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

回答by Dave Batton

Notice that UICollectionViewCellhas a selectedBackgroundViewproperty. By default, it's nil. Just create a view for this property, and it will appear when the user touches the cell.

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

回答by JakubKnejzlik

Well...as all of these methods are correct. I've found the way that seems like the easiest one to me. Just override the setSelected: method (for example to change background color):

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

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

...it works "out of the box" (even with collectionView.allowsMultipleSelection)

...它“开箱即用”(即使使用 collectionView.allowsMultipleSelection)

回答by Viktor

It is enough for highlighting cell (Swift 4)

突出显示单元格就足够了(Swift 4)

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

回答by Brody Robertson

As taken directly from UICollectionViewCell.h - overriding both setSelectedand setHighlightedare correct. Depending upon your situation you might consider assigning custom views to backgroundViewand selectedBackgroundViewwhich are swapped automatically on selection.

直接取自 UICollectionViewCell.h - 覆盖两者setSelected并且setHighlighted是正确的。根据您的情况,您可能会考虑将自定义视图分配给backgroundView以及selectedBackgroundView在选择时自动交换的视图。

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

回答by oOEric

Swift 3: (based on the answer of A-Live)

Swift 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

斯威夫特 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
    }
}