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,如果您更改视图图层边框属性,这些属性将被保留)
这里是触摸单元格的函数调用序列
- setHighlighted
- touchesEnded
- layoutSubviews
- willSelectRowAtIndexPath(委托方)
- setSelected(!!!这是所有的视图背景颜色被告知消失的地方)
- didSelectRowAtIndexPath(委托方)
- setSelected(again)(有趣的是,在这个调用中没有清除背景颜色,在这个超级方法里面发生了什么奇怪的事情?)
- layoutSubviews(再次)
所以你的select是
- Override – (void)setSelected:(BOOL)selected animated:(BOOL)animated; 不需要调用[super setSelected:selected animated:animated] 。 这将给你在技术上最正确的实现,因为a)代码被包装在UITableViewCell子类中,b)因为它只在需要的时候调用(在需要的时候两次,但也许有一种方法)。 不好的一面是你必须重新实现setSelected的所有必要的function(而不是不必要的颜色清除function)。 现在不要问我如何正确覆盖setSelected。 你的猜测和我现在的一样好(耐心点,一旦弄明白,我会编辑这个答案)。
- 在didSelectRowAtIndexPath中重新声明背景颜色。 这不是很好,因为它把实例代码放在实例之外。 它有一个好处,它只是在需要的时候才被调用,而不是…
- 在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
被选中时,你需要注意两个状态: Highlighted
和Selected
。
因此,对于具有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中工作。
- 覆盖
setSelected
和setHighlighted
- 不要叫超级
- 清除
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 }