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
Where to highlight UICollectionViewCell: delegate or cell?
提问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, UICollectionViewCell
manages its highlighted state independently, via the highlighted
property.
我不喜欢这种方法的一点是它向委托添加了非常特定于单元格的逻辑。事实上,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 highlighted
property 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 UICollectionViewCell
has a selectedBackgroundView
property. 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 setSelected
and setHighlighted
are correct. Depending upon your situation you might consider assigning custom views to backgroundView
and selectedBackgroundView
which 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
}
}