2011-07-19 86 views
139

我正在实现一个颜色选择器表格视图,用户可以在其中选择10种颜色(取决于产品)。用户也可以选择其他选项(如硬盘容量,...)。当选择单元格时,UITableViewCell子视图消失

所有颜色选项都在它们自己的tableview部分中。

我想在textLabel的左侧显示一个小正方形,显示实际的颜色。

现在我加入了简单的方形的UIView,给它正确的背景颜色,就像这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:RMProductAttributesCellID]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:RMProductAttributesCellID] autorelease]; 
     cell.indentationWidth = 44 - 8; 

     UIView *colorThumb = [[[UIView alloc] initWithFrame:CGRectMake(8, 8, 28, 28)] autorelease]; 
     colorThumb.tag = RMProductAttributesCellColorThumbTag; 
     colorThumb.hidden = YES; 
     [cell.contentView addSubview:colorThumb]; 
    } 

    RMProductAttribute *attr = (RMProductAttribute *)[_product.attributes objectAtIndex:indexPath.section]; 
    RMProductAttributeValue *value = (RMProductAttributeValue *)[attr.values objectAtIndex:indexPath.row]; 
    cell.textLabel.text = value.name; 
    cell.textLabel.backgroundColor = [UIColor clearColor]; 

    UIView *colorThumb = [cell viewWithTag:RMProductAttributesCellColorThumbTag]; 
    colorThumb.hidden = !attr.isColor; 
    cell.indentationLevel = (attr.isColor ? 1 : 0); 

    if (attr.isColor) { 
     colorThumb.layer.cornerRadius = 6.0; 
     colorThumb.backgroundColor = value.color; 
    } 

    [self updateCell:cell atIndexPath:indexPath]; 

    return cell; 
} 

这显示没有问题的罚款。

我唯一的问题是,当我选择一个“颜色”行,在渐变到蓝色选择动画期间,我的自定义UIView(colorThumb)被隐藏。它在选择/取消选择动画结束后再次可见,但是这会产生一个丑陋的工件。

我该怎么做才能纠正这个问题?不要在正确的地方插入子视图?

(没有什么特别的didSelectRowAtIndexPath,我只是将单元格的附件更改为复选框或没有任何内容,并取消选择当前的indexPath)。

+0

什么upadteCell一回事呢? – Idan

+0

updateCell会进行一些微小的调整,如设置选中标记或不选中,根据可用性选择文本颜色,但不会涉及单元格本身或colorThumb。 – Cyrille

+0

接受的答案不提供解决方案,请参阅我的答案以下解答 –

回答

162

UITableViewCell当单元格被选中或突出显示时更改所有子视图的背景颜色,您可以通过覆盖Tableview单元格的setSelected:animatedsetHighlighted:animated并重置视图背景颜色来解决此问题。

在Objective C:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated { 
    UIColor *color = self.yourView.backgroundColor;   
    [super setSelected:selected animated:animated]; 

    if (selected){ 
     self.yourView.backgroundColor = color; 
    } 
} 

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{ 
    UIColor *color = self.yourView.backgroundColor;   
    [super setHighlighted:highlighted animated:animated]; 

    if (highlighted){ 
     self.yourView.backgroundColor = color; 
    } 
} 

在夫特3。1:

override func setSelected(_ selected: Bool, animated: Bool) { 
    let color = yourView.backgroundColor   
    super.setSelected(selected, animated: animated) 

    if selected { 
     yourView.backgroundColor = color 
    } 
} 

override func setHighlighted(_ highlighted: Bool, animated: Bool) { 
    let color = yourView.backgroundColor 
    super.setHighlighted(highlighted, animated: animated) 

    if highlighted { 
     yourView.backgroundColor = color 
    } 
} 
+1

这应该是答案。 –

+0

我们是否需要'if(突出显示)'和'if(selected)'条件?如果我们没有这些条件,我认为它会起作用。 –

+0

@Cyrille这个行为应该被接受为最佳解决方案。 – arts777

120

这是因为表格视图单元格会自动更改内容视图中所有视图的背景色以突出显示状态。您可以考虑继承UIView以绘制颜色或使用UIImageView自定义1x1像素拉伸图像。

+1

哑我。当然就是这样,子视图必须是透明的,以便选择动画可以正确地发生。谢谢! – Cyrille

+49

或者你可以重新设置背景颜色覆盖'setHighlighted:animated:'和'setSelected:animated:' – pt2ph8

+0

谢谢你们,我遇到了同样的问题,真的有所帮助。 – ratsimihah

9

另一种方式来管理问题,以填补核心图形渐变的观点,如:

CAGradientLayer* gr = [CAGradientLayer layer]; 
gr.frame = mySubview.frame; 
gr.colors = [NSArray arrayWithObjects: 
        (id)[[UIColor colorWithRed:0 green:0 blue:0 alpha:.5] CGColor] 
        ,(id)[[UIColor colorWithRed:0 green:0 blue:0 alpha:.5] CGColor] 
        , nil]; 

gr.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0],[NSNumber numberWithFloat:1],nil]; 

[mySubview.layer insertSublayer:gr atIndex:0]; 
+0

+1,因为这是我最近一直在做的事情。 – Cyrille

+0

嗯,我正在尝试这个确切的代码,它对我没有任何影响。我的子视图是一个UILabel作为cell.contentView的子视图添加,并在iOS 6.0.1下进行测试,以防万一。 –

+0

你对上面的代码应用了什么?你有没有尝试将标签添加到单元格视图? – Agat

3

的UITableViewCell上选择改变的backgroundColor所有子视图出于某种原因。

这可能帮助:

DVColorLockView

使用类似的东西,从选取过程中更改您的视图颜色停止的UITableView。

0

这里是我的解决方案,使用内容查看显示selectionColor设置,它的工作完美

#import "BaseCell.h" 

@interface BaseCell() 
@property (nonatomic, strong) UIColor *color_normal; 
@property (nonatomic, assign) BOOL needShowSelection; 
@end 


@implementation BaseCell 
@synthesize color_customSelection; 
@synthesize color_normal; 
@synthesize needShowSelection; 

- (void)awakeFromNib 
{ 
    [super awakeFromNib]; 
    [self setup]; 
} 

- (void)setup 
{ 
    //save normal contentView.backgroundColor 
    self.color_normal = self.backgroundColor; 
    if (self.color_normal == nil) { 
     self.color_normal = [UIColor colorWithRGBHex:0xfafafa]; 
    } 
    self.color_customSelection = [UIColor colorWithRGBHex:0xF1F1F1]; 
    self.accessoryView.backgroundColor = [UIColor clearColor]; 
    if (self.selectionStyle == UITableViewCellSelectionStyleNone) { 
     needShowSelection = NO; 
    } 
    else { 
     //cancel the default selection 
     needShowSelection = YES; 
     self.selectionStyle = UITableViewCellSelectionStyleNone; 
    } 
} 

/* 
solution is here 
*/ 
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesBegan:touches withEvent:event]; 
    if (needShowSelection) { 
     self.contentView.backgroundColor = self.backgroundColor = color_customSelection; 
    } 
} 

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesCancelled:touches withEvent:event]; 
    if (needShowSelection) { 
     self.contentView.backgroundColor = self.backgroundColor = color_normal; 
    } 
} 

- (void)setSelected:(BOOL)selected animated:(BOOL)animated 
{ 
    [super setSelected:selected animated:animated]; 
    if (needShowSelection) { 
     UIColor *color = selected ? color_customSelection:color_normal; 
     self.contentView.backgroundColor = self.backgroundColor = color; 
    } 
} 
3

通过 Yatheesha B Lanswer 我创建一个UITableViewCell类/扩展,可以让你的启发打开和关闭此透明度“功能”。

夫特

let cell = <Initialize Cell> 
cell.keepSubviewBackground = true // Turn transparency "feature" off 
cell.keepSubviewBackground = false // Leave transparency "feature" on 

目标C

UITableViewCell* cell = <Initialize Cell> 
cell.keepSubviewBackground = YES; // Turn transparency "feature" off 
cell.keepSubviewBackground = NO; // Leave transparency "feature" on 

KeepBackgroundCell是的CocoaPods兼容。你可以找到它on GitHub

+0

流利地为我工作! –

6

您可以cell.selectionStyle = UITableViewCellSelectionStyleNone;, 然后设置的backgroundColor在- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath

22

找到一个漂亮优雅的解决方案,而不是与tableViewCell选择搞乱/高亮方法。您可以创建UIView的子类,忽略设置其背景颜色以清除颜色。

夫特3/4:

class NeverClearView: UIView { 
    override var backgroundColor: UIColor? { 
     didSet { 
      if backgroundColor != nil && backgroundColor!.cgColor.alpha == 0 { 
       backgroundColor = oldValue 
      } 
     } 
    } 
} 

夫特2:

class NeverClearView: UIView { 
    override var backgroundColor: UIColor? { 
     didSet { 
      if CGColorGetAlpha(backgroundColor!.CGColor) != 0 { 
       backgroundColor = oldValue 
      } 
     } 
    } 
} 

的OBJ-C版本:

@interface NeverClearView : UIView 

@end 

@implementation NeverClearView 

- (void)setBackgroundColor:(UIColor *)backgroundColor { 
    if (CGColorGetAlpha(backgroundColor.CGColor) != 0) { 
     [super setBackgroundColor:backgroundColor]; 
    } 
} 

@end 
+0

这很可爱。如果您有一些可重复使用的视图,如“徽章”或“标签”,应该永远不会有清晰的背景,那么最容易找到最佳解决方案。 :: rant ::多么混乱的解决方案@UIKit,当你做一个单元格选择时,将所有子视图设置为透明。至少限制为单元格的全高或宽度的子视图或N个深度的子视图。 – SimplGy

+0

@SimplGy突出显示的深度确实是一个很好的选择,但嘿 - 这是UIKit,我看到的事情比这更糟糕=) –

+3

在我更改if后改为CGColorGetAlpha(backgroundColor!.CGColor)= = 0,因为它不等于clearColor – piltdownman7

1

绘制,而不是设置背景颜色的视图

import UIKit 

class CustomView: UIView { 

    var fillColor:UIColor! 

    convenience init(fillColor:UIColor!) { 
     self.init() 
     self.fillColor = fillColor 
    } 

    override func drawRect(rect: CGRect) { 
     if let fillColor = fillColor { 
      let context = UIGraphicsGetCurrentContext() 
      CGContextSetFillColorWithColor(context, fillColor.CGColor); 
      CGContextFillRect (context, self.bounds); 

     } 
    } 


} 
6

对于雨燕2.2这个作品

cell.selectionStyle = UITableViewCellSelectionStyle.None 

和理性是由@Andriy

解释说这是因为表视图单元格自动改变的 高亮显示状态的内容视图中的所有视图的背景颜色。

+1

短而简单,工作就像一个魅力。谢谢:) –

+1

简单而完美的工作 –

0

尝试下面的代码:

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated 
{  
[super setHighlighted:highlighted animated:animated]; 
//Set your View's Color here. 
} 
0

基于保罗·古罗夫的答案我实现了在Xamarin.iOS以下。 C#版本:

NeverClearView.cs

public partial class NeverClearView : UIView 
{ 
    public NeverClearView(IntPtr handle) : base(handle) 
    { 
    } 

    public override UIColor BackgroundColor 
    { 
     get 
     { 
      return base.BackgroundColor; 
     } 
     set 
     { 
      if (value.CGColor.Alpha == 0) return; 

      base.BackgroundColor = value; 
     } 
    } 
} 

NeverClearView.designer。CS

[Register("NeverClearView")] 
partial class NeverClearView 
{ 
    void ReleaseDesignerOutlets() 
    { 
    } 
} 
0

不要忘了覆盖setSelected以及setHighlighted

override func setHighlighted(highlighted: Bool, animated: Bool) { 

    super.setHighlighted(highlighted, animated: animated) 
    someView.backgroundColor = .myColour() 
} 

override func setSelected(selected: Bool, animated: Bool) { 

    super.setSelected(selected, animated: animated) 
    someView.backgroundColor = .myColour() 
} 
0

将此代码放在您的UITableViewCell

子斯威夫特3语法

override func setSelected(_ selected: Bool, animated: Bool) { 
    super.setSelected(selected, animated: animated) 

    if(selected) { 
     lockerSmall.backgroundColor = UIColor.init(red: 233/255, green: 106/255, blue: 49/255, alpha: 1.0) 
    } 
} 


override func setHighlighted(_ highlighted: Bool, animated: Bool) { 
    super.setHighlighted(highlighted, animated: animated) 

    if(highlighted) { 
     lockerSmall.backgroundColor = UIColor.init(red: 233/255, green: 106/255, blue: 49/255, alpha: 1.0) 
    } 
} 
0

T他与Pavel Gurov的答案类似,但更灵活,因为它允许任何颜色永久。

class PermanentBackgroundColorView: UIView { 
    var permanentBackgroundColor: UIColor? { 
     didSet { 
      backgroundColor = permanentBackgroundColor 
     } 
    } 

    override var backgroundColor: UIColor? { 
     didSet { 
      if backgroundColor != permanentBackgroundColor { 
       backgroundColor = permanentBackgroundColor 
      } 
     } 
    } 
} 
0

如果您使用的是故事板,请添加其他解决方案。创建一个UIView的子类,它不允许backgroundColor在初始设置之后进行设置。

@interface ConstBackgroundColorView : UIView 

@end 

@implementation ConstBackgroundColorView 

- (void)setBackgroundColor:(UIColor *)backgroundColor { 
    if (nil == self.backgroundColor) { 
     [super setBackgroundColor:backgroundColor]; 
    } 
} 

@end 
0

如果上述背景溶液不修理你的问题,您的问题可能在于你的datasource您的tableView。

对于我来说,我创建一个数据源对象(称为BoxDataSource)的一个实例来处理的委托和数据源的tableView方法,像这样:

//In cellForRowAtIndexPath, when setting up cell 
let dataSource = BoxDataSource(delegate: self) 
cell.tableView.dataSource = dataSource 
return cell 

这是导致数据源被释放每当细胞被窃听,因此所有的内容都消失了。原因是,ARC释放/垃圾收集的性质。

为了解决这个问题,我不得不去到自定义单元格,添加一个数据源变量:

//CustomCell.swift 
var dataSource: BoxDataSource? 

然后,你需要设置的数据源var你只是在cellForRow创建的单元格的数据源,所以这未与ARC重新分配。

cell.statusDataSource = BoxAssigneeStatusDataSource(delegate: self) 
cell.detailsTableView.dataSource = cell.statusDataSource 
return cell 

希望有所帮助。

2

Yatheesha B L的回答启发。

如果您调用super.setSelected(选定,动画:动画),它将清除您设置的所有背景色。所以,我们不会调用超级方法。

在斯威夫特:

override func setSelected(selected: Bool, animated: Bool) {  
    if(selected) { 
     contentView.backgroundColor = UIColor.red 
    } else { 
     contentView.backgroundColor = UIColor.white 
    } 
} 

override func setHighlighted(highlighted: Bool, animated: Bool) { 
    if(highlighted) { 
     contentView.backgroundColor = UIColor.red 
    } else { 
     contentView.backgroundColor = UIColor.white 
    } 
} 
+0

感谢您的解决方案。 +1 重写ishiglighted变量和sethighlighted方法是不同的事情。正确的答案是重写该方法。 –

0

我想保持不同的是,我想忽略自动背景色改变一个单元子视图的默认选择行为。但我还需要能够在其他时间更改背景颜色。

我想出的解决方案是子类UIView,所以它忽略了正常设置背景颜色并添加一个单独的函数来绕过保护。

斯威夫特4

class MyLockableColorView: UIView { 
    func backgroundColorOverride(_ color: UIColor?) { 
      super.backgroundColor = color 
    } 

    override var backgroundColor: UIColor? { 
     set { 
      return 
     } 
     get { 
      return super.backgroundColor 
     } 
    } 
} 
相关问题