2011-03-07 78 views
58

我有一个简单的tableViewCell构建在界面生成器中。 它包含一个包含图像的UIView。 现在,当我选择单元格时,会显示默认的蓝色选择背景,但我的UIView的backgroundColor已消失。UIView backgroundColor当UITableViewCell被选中时消失

我的UITableViewCell的实现文件没有做任何特别的事情。它只是初始化的&返回self,我在setSelected中做的所有操作都是超级调用。

如何获取我的UIView backgroundColor以显示何时选择tableView?

+0

还有哪些其他的界面元素的视图中,即得到由小区选择颜色覆盖? – hennes 2011-03-07 17:48:53

+0

目前这只是一个图像。这是为了使图像看起来像一张照片。稍后,我还会在那里添加一个标签。 – P5ycH0 2011-03-07 18:21:20

回答

96

这里的问题是,[超级]实施

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

将所有的背景颜色中的UITableViewCell到RGBA(0,0,0,0)。为什么?也许让我们都汗流?背?

这并不是说整个的看法消失

这里(的事实,如果你改变了看法层边框属性,这些被保留作为证据)是函数的调用序列,从触摸细胞

结果
  1. setHighlighted
  2. touchesEnded
  3. layoutSubviews
  4. willSelectRowAtIndexPath(委托侧)
  5. setSelected(!!!这是你的所有观察背景色被告知消失)
  6. didSelectRowAtIndexPath方法(委托方)
  7. 的setSelected(再次)(有趣的是背景颜色不清除此调用。该超法里面是怎么回事什么奇怪?)
  8. layoutSubviews(再次)

所以,你的选择是

  1. 覆盖- (空)的setSelected:选择动画(BOOL)(布尔)ANI配合;没有致电[super setSelected:选择动画:动画]。这会给你最正确的技术实现,因为a)代码被包装在UITableViewCell子类中,b)因为它只在需要的时候被调用(在需要的时候会被调用两次,但也许有解决方法)。不利的一面是你必须重新实现setSelected的所有必要功能(而不是不必要的颜色清除功能)。现在不要问我如何正确覆盖setSelected了。你的猜测和我现在一样好(耐心等待,一旦我弄明白了,我会编辑这个答案)。
  2. 重新断言didSelectRowAtIndexPath中的背景颜色。这不是太好,因为它将实例代码放在实例外。它有一个好处,它只在需要时才被调用,而不是...
  3. 重新断言背景颜色layoutSubviews。这并不好,因为layoutSubviews被称为百万倍!每次餐桌刷新时,每次滚动时,都会调用它,每当祖母得到烫发时......就像是认真的,一百万次。这意味着有很多不必要的背景重新断言和大量额外的处理开销。好的一面是它将代码放在UITableViewCell子类中,这很好。

不幸的是重新断言在setHighlighted背景颜色不执行任何操作,因为之前所有的背景颜色都将置到setHighlighted称为[R:0 B:0 G:0:0]由第一次调用的setSelected。

// TODO:给如何重写的setSelected一个伟大的说明(敬请关注)

+1

之前,背景颜色似乎已被清除。非常有意义!我会继续关注覆盖;-) – P5ycH0 2012-02-21 09:40:16

+0

只是跟进。我已经搞砸了这一点,但仍然没有找到我会称为重写setSelected的干净,通用的解决方案。如果/当我这样做,我会发布更多的信息.​​...快乐的编码 – Brooks 2012-05-15 20:46:53

+0

感谢光明日增加压力! – amcc 2013-04-24 19:40:44

0

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

从参考:

一个UITableViewCell对象的内容视图是由该单元所显示的内容的缺省上海华。如果您想通过简单地添加附加视图来自定义单元格,则应该将它们添加到内容视图中,以便在单元格进入和退出编辑模式时适当定位它们。

+0

我在InterfaceBuilders中查看hierachie UITableViewCell是TableViewCell> View> ImageView。如果我使用代码构建tableViewCell,我可能会错误地将视图添加到tableviewcell的视图而不是contentView中,但我不明白我如何在IB中犯这个错误...请注意,我的图像正在显示,但父视图元素不是。 – P5ycH0 2011-03-07 18:41:05

3

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

0

您可以通过覆盖UITableViewCell类中的setHighlighted函数(您将需要继承它)来更改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"]; 
    } 
} 

您也可以改变选择模式为灰色,在界面生成器的蓝色或无。

+0

是的,我知道。但那不是我的问题。我想知道,如果在选定的tableviewcell上,我可以防止丢失基于UIView的元素的背景颜色。我通过使用imageview而不是视图找到了解决方法。 – P5ycH0 2011-03-11 21:38:20

+0

还有更多信息:在我最近的测试中,我发现每次选择一个单元格后,背景颜色都会被清除,而不仅仅是在初始化之后或你有什么。事件序列似乎是1)setHighlighted调用2)touchesEnded调用3)layoutSubviews调用4)didSelectRowAtIndexPath调用4)layoutSubviews再次调用。在didSelectRowAtIndexPath – Brooks 2012-02-17 20:30:13

4

布鲁克斯为什么发生这种情况的很好的解释,但我想我有一个更好的解决方案。

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

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

此前我已经照@ P5ycH0说(1x1图片拉伸),但以下@Brooks我想通覆盖在我的自定义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; 
} 
+0

这对我来说算得了。 – 2013-11-15 16:33:12

+1

最佳解决方案 – 2014-04-15 22:59:07

+0

感谢您搜索了2天 – sanjeev 2014-05-17 07:07:34

2

你需要重写你的自定义单元格的下两种方法:

- (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财产。

62
- (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; 
} 
+0

伟大的解决方案。比所有子类和CALayer解决方案都要干净得多。 – Joel 2014-09-15 04:23:12

+0

谢谢!您的解决方案是最好的! – Insider 2016-04-29 12:17:48

+0

这对我来说是最有用的答案。 [修改](https://stackoverflow.com/a/45882764/991856)稍微为我的用例(多个单元格带有多个锁定的背景视图),但工作解决方案的荣誉! – Yasir 2017-08-25 13:43:45

0

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

这让我保持系统的默认选择动画当用户点击该单元格,也可以取消选择在表视图委托的didSelectRowAtIndexPath:

0

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

1

这对你的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() 
     }) 
    } 
} 
1

相关添加到@布鲁克斯的答案,这是我做的,使其在斯威夫特和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() 
        } 
    } 
    
12

当选择你的UITableViewCell,还有你要注意两种状态:HighlightedSelected

所以,你有一个自定义单元格类是UITableViewCell子类的场景,你可以很容易地覆盖这两个方法来避免这种情况(SWIFT):

class MyCell: UITableViewCell { 

    @IBOutlet var myView: UIView! 

    override func setHighlighted(highlighted: Bool, animated: Bool) { 
     let myViewBackgroundColor = myView.backgroundColor 
     super.setHighlighted(highlighted, animated: animated) 
     myView.backgroundColor = myViewBackgroundColor 
    } 

    override func setSelected(selected: Bool, animated: Bool) { 
     let myViewBackgroundColor = myView.backgroundColor 
     super.setSelected(selected, animated: animated) 
     myView.backgroundColor = myViewBackgroundColor 
    } 

} 
+0

swift的最佳答案 – sleepwalkerfx 2016-10-18 07:08:27

0

以下是一张就可以了。我有我的所有细胞从继承的子类,所以这是我这样做是为了避免在我UIImageViews的背景变化的方式:

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

0

摘要

这个解决方案让我们你锁定某些单元格的背景颜色,其余由系统行为的控制。


基于mientus' answer,我创建了一个解决方案,它可以让你指定哪些意见应保持其背景颜色

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

我使用的面向协议的方法,用含有视图锁定列表中,并运行一个闭合,同时保持颜色的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一个子类,其覆盖突出显示和选择奔波调用默认(超)行为协议的终止:

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原在一个单元格类中添加锁定行为,以便轻松添加到某些单元格中

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

斯威夫特4

在你的UITableViewCell类:

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

override func setHighlighted(_ highlighted: Bool, animated: Bool) { 
    myView.backgroundColor = UIColor.blue 
} 
相关问题