UIView backgroundColor当UITableViewCell被选中时消失

我有一个简单的tableViewCell构build在界面生成器。 它包含一个包含图像的UIView。 现在,当我select单元格时,会显示默认的蓝色select背景,但是我的UIView的backgroundColor不见了。

我的UITableViewCell的实现文件没有做任何特殊的事情。 它只是init的&返回自我,我所做的setSelected是超级呼叫。

如何让我的UIView backgroundColor显示何时selecttableView?

这里的问题是[超]执行

- (void) setSelected:(BOOL) selected animated:(BOOL) animated; 

将UITableViewCell中的所有背景颜色设置为rgba(0,0,0,0)。 为什么? 也许让我们都汗stream</s>背?

这并不是说整个视图消失(事实certificate,如果您更改视图图层边框属性,这些属性将被保留)

这里是触摸单元格的函数调用序列

  1. setHighlighted
  2. touchesEnded
  3. layoutSubviews
  4. willSelectRowAtIndexPath(委托方)
  5. setSelected(!!!这是所有的视图背景颜色被告知消失的地方)
  6. didSelectRowAtIndexPath(委托方)
  7. setSelected(again)(有趣的是,在这个调用中没有清除背景颜色,在这个超级方法里面发生了什么奇怪的事情?)
  8. layoutSubviews(再次)

所以你的select是

  1. Override – (void)setSelected:(BOOL)selected animated:(BOOL)animated; 不需要调用[super setSelected:selected animated:animated] 。 这将给你在技术上最正确的实现,因为a)代码被包装在UITableViewCell子类中,b)因为它只在需要的时候调用(在需要的时候两次,但也许有一种方法)。 不好的一面是你必须重新实现setSelected的所有必要的function(而不是不必要的颜色清除function)。 现在不要问我如何正确覆盖setSelected。 你的猜测和我现在的一样好(耐心点,一旦弄明白,我会编辑这个答案)。
  2. didSelectRowAtIndexPath中重新声明背景颜色。 这不是很好,因为它把实例代码放在实例之外。 它有一个好处,它只是在需要的时候才被调用,而不是…
  3. layoutSubviews中重新声明背景颜色。 这并不好,因为layoutSubviews被称为百万倍! 每当表格刷新时,每次滚动时,都会调用它,每当你奶奶烫发时,就会严重到百万次。 这意味着有很多不必要的背景重新声明和大量额外的处理开销。 在好的一面,它把代码放在UITableViewCell子类中,这很好。

不幸的是,在setHighlighted中重新声明背景颜色不会做任何事情,因为在首先调用setSelected之前,在所有背景颜色设置为[r:0 b:0 g:0 a:0]之前调用setHighlighted。

// TODO:给出如何覆盖setSelected(敬请关注)

 - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { UIColor *backgroundColor = self.channelImageView.backgroundColor; [super setHighlighted:highlighted animated:animated]; self.channelImageView.backgroundColor = backgroundColor; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { UIColor *backgroundColor = self.channelImageView.backgroundColor; [super setSelected:selected animated:animated]; self.channelImageView.backgroundColor = backgroundColor; } 

以前我做@ P5ycH0表示(1×1图像拉伸),但在@Brooks我认为覆盖-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated在我的自定义UITableViewCell实现-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated和重置后的背景颜色调用[super setHighlighted:highlighted animated:animated]; 当单元格被选中/突出显示时保持我的背景颜色

 -(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; myView.backgroundColor = myColor; } 

当你的UITableViewCell被选中时,你需要注意两个状态: HighlightedSelected

因此,对于具有UITableViewCell子类的自定义单元类的场景,您可以轻松地重写这两种方法来避免这种情况(Swift):

 class MyCell: UITableViewCell { @IBOutlet weak var myView: UIView? override func setHighlighted(highlighted: Bool, animated: Bool) { var color = self.myView!.backgroundColor // Store the color super.setHighlighted(highlighted, animated: animated) self.myView?.backgroundColor = color } override func setSelected(selected: Bool, animated: Bool) { var color = self.myView!.backgroundColor // Store the color super.setSelected(selected, animated: animated) self.myView?.backgroundColor = color } } 

布鲁克斯为什么发生这种事情有一个很好的解释,但我认为我有一个更好的解决scheme。

在你的子视图中,覆盖setBackgroundColor:你想要什么颜色。 二传手仍将被调用,但只有您指定的颜色将被强制执行。

 - (void)setBackgroundColor:(UIColor *)backgroundColor { [super setBackgroundColor:[UIColor whiteColor]]; } 

好吧,丢失一个UIView类的背景颜色是正常的行为,当它在一个选定的tableviewcell。 我无法弄清楚如何防止这种情况。 现在我刚刚用一个包含拉伸的1×1白色像素的UIImageViewreplace了UIView。 丑陋的艾莫,但它的作品。

您需要覆盖自定义单元格中的下两个方法:

 - (void) setSelected:(BOOL)selected animated:(BOOL)animated; - (void) setHighlighted:(BOOL)highlighted animated:(BOOL)animated; 

注意:

  • 你应该在自定义实现或相应的方法开始时调用[super setSelected:animated:][super setHighlighted:animated:] ;
  • 您应该为您的自定义单元格设置UITableViewCellSelectionStyleNone selectionStyle,以禁用任何默认的UITableViewCell样式;

这里是实现的例子:

 - (void) setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; [self setHighlightedSelected:highlighted animated:animated]; } - (void) setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; [self setHighlightedSelected:selected animated:animated]; } - (void) setHighlightedSelected:(BOOL)selected animated:(BOOL)animated { void(^selection_block)(void) = ^ { self.contentView.backgroundColor = selected ? SELECTED_BACKGROUND_COLOR : NORMAL_BACKGROUND_COLOR; }; if(animated) { [UIView animateWithDuration:SELECTION_ANIMATION_DURATION delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:selection_block completion:NULL]; } else selection_block(); } 

contentView是iOS 7中出现的UITableViewCell的属性。请注意,您可以使用您自己的单元格的子视图或视图来代替它。

将此添加到您的UITableViewCell

 override func setHighlighted(highlighted: Bool, animated: Bool) { super.setHighlighted(false, animated: animated) if highlighted { self.backgroundColor = UIColor.blueColor() }else{ UIView.animateWithDuration(0.2, animations: { self.backgroundColor = UIColor.clearColor() }) } } 

相关@布鲁克斯的答案,这是我做了什么使它在Swift和iOS8 / iOS9中工作。

  • 覆盖setSelectedsetHighlighted
  • 不要叫超级
  • 清除contentView.backgroundColor ,因为它不必跨越整个单元格宽度(即配件)。
  • 使用单元格本身的backgroundColor ,并相应地进行设置。

     class AwesomeTableViewCell: UITableViewCell { private struct Constants { static var highlightedColor = UIColor.greenColor() static var selectedColor = UIColor.redColor() static let animationTime = NSTimeInterval(0.2) } override func awakeFromNib() { super.awakeFromNib() contentView.backgroundColor = UIColor.clearColor() backgroundColor = AppContext.sharedInstance.theme.colors.background } override func setHighlighted(highlighted: Bool, animated: Bool) { if animated { UIView.animateWithDuration(Constants.animationTime, animations: { () -> Void in self.setHighlighted(highlighted) }) } else { self.setHighlighted(highlighted) } } override func setSelected(selected: Bool, animated: Bool) { if animated { UIView.animateWithDuration(Constants.animationTime, animations: { () -> Void in self.setSelected(selected) }) } else { self.setSelected(selected) } } private func setHighlighted(highlighted: Bool) { backgroundColor = highlighted ? Constants.highlightedColor : UIColor.whiteColor() } private func setSelected(selected: Bool) { backgroundColor = selected ? Constants.selectedColor : UIColor.whiteColor() } } 

从你说你build立了一个tableViewCell使用IB,我想检查你是否添加您的视图作为UITableViewCell contentView的子视图,而不是view 。 内容视图是单元格显示内容的默认超级视图。

从参考:

UITableViewCell对象的内容视图是单元格显示内容的默认超级视图。 如果要通过简单地添加其他视图来自定义单元格,则应将其添加到内容视图中,以便在单元格进入和退出编辑模式时适当地定位它们。

您可以通过覆盖UITableViewCell类中的setHighlighted函数(您将需要从中inheritance)来更改tableViewCell的行为。 我的代码,我改变我的单元格的背景图像的例子:

 // animate between regular and highlighted state - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated; { [super setHighlighted:highlighted animated:animated]; //Set the correct background Image UIImageView* backgroundPicture = (UIImageView*)[self viewWithTag:HACK_BACKGROUND_VIEW_TAG]; if (highlighted) { backgroundPicture.image = [UIImage imageNamed:@"FondSelected.png"]; } else { backgroundPicture.image = [UIImage imageNamed:@"Fond.png"]; } } 

您还可以在界面生成器中将select模式更改为灰色,蓝色或无。

在iOS 7中,我的工作是覆盖UITableViewCell子类中的setSelected:animated: :,但与@Brooks的提示相反,我调用了[super setSelected:selected animated:animated]

 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Reassert the background color of the color view so that it shows // even when the cell is highlighted for selection. self.colorView.backgroundColor = [UIColor blueColor]; } 

这可以让我在用户点击单元格时保持系统的默认selectanimation,也可以在表视图中取消select委托的didSelectRowAtIndexPath:

刚在这个奇怪的问题上花了一些时间。 我不想设置UITableViewCellSelectionStyleNone样式来保存好我的行被选中时的animation。 但没有任何build议的想法为我工作 – 我试图覆盖setSelected和setHighlighted并设置我的子视图backgroundColor那里 – 它保持iOS重置,并仍然闪烁(新颜色 – >旧颜色)。 对我来说修复很简单。 当我的行被选中时,另一个视图控制器被按下,用户在该屏幕上select一些选项,并根据用户select改变颜色来调用委托。 在这个代表中,我只是为我的单元格[单元格setSelected:NO animated:NO]。 (我有静态UITableViewController和单元格的网点)。 你可能可以取消select在didSelect方法中的单元格,但在我的情况下,我正在使用segues。

这是我的承诺。 我有一个子类,所有我的细胞inheritance,所以这样做是为了避免我的UIImageView中的背景更改:

  override func setHighlighted(highlighted: Bool, animated: Bool) { var backgroundColors = [UIView: UIColor]() for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { backgroundColors[imageView] = imageView.backgroundColor } } super.setHighlighted(highlighted, animated: animated) for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { imageView.backgroundColor = backgroundColors[imageView] } } } override func setSelected(selected: Bool, animated: Bool) { var backgroundColors = [UIView: UIColor]() for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { backgroundColors[imageView] = imageView.backgroundColor } } super.setSelected(selected, animated: animated) for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { imageView.backgroundColor = backgroundColors[imageView] } } } 

这自动地解决了所有UIImageView的问题。

概要

这个解决scheme让你locking一些单元格的背景颜色 ,而其余​​的则由系统行为控制。


基于mientus的回答 ,我已经创build了一个解决scheme,允许您指定哪些视图应保持其背景颜色

这仍然允许其他单元格子视图的突出显示/select的背景删除,并且是唯一的解决scheme,在我们的案件(两个视图需要永久背景)的作品。

我使用了面向协议的方法,使用包含要locking的视图列表的BackgroundLockable协议,并在保持颜色的同时运行闭包:

 protocol BackgroundLockable { var lockedBackgroundViews: [UIView] { get } func performActionWithLockedViews(_ action: @escaping () -> Void) } extension BackgroundLockable { func performActionWithLockedViews(_ action: @escaping () -> Void) { let lockedViewToColorMap = lockedBackgroundViews.reduce([:]) { (partialResult, view) -> [UIView: UIColor?] in var mutableResult = partialResult mutableResult[view] = view.backgroundColor return mutableResult } action() lockedViewToColorMap.forEach { (view: UIView, color: UIColor?) in view.backgroundColor = color } } } 

然后我有一个UITableViewCell的子类,它覆盖突出显示和select,以调用默认(超)行为运行协议的闭包:

 class LockableBackgroundTableViewCell: UITableViewCell, BackgroundLockable { var lockedBackgroundViews: [UIView] { return [] } override func setHighlighted(_ highlighted: Bool, animated: Bool) { performActionWithLockedViews { super.setHighlighted(highlighted, animated: animated) } } override func setSelected(_ selected: Bool, animated: Bool) { performActionWithLockedViews { super.setSelected(selected, animated: animated) } } } 

现在,我只需要LockableBackgroundTableViewCell子类,或者在单元类中使用BackgroundLockable协议,以便轻松地将locking行为添加到某些单元格!

 class SomeCell: LockableBackgroundTableViewCell { @IBOutlet weak var label: UILabel! @IBOutlet weak var icon: UIImageView! @IBOutlet weak var button: UIButton! override var lockedBackgroundViews: [UIView] { return [label, icon] } } 

斯威夫特4

在你的UITableViewCell类中:

 override func setSelected(_ selected: Bool, animated: Bool) { myView.backgroundColor = UIColor.blue } override func setHighlighted(_ highlighted: Bool, animated: Bool) { myView.backgroundColor = UIColor.blue }