我当前项目的UITableViewCell行为令我感到困惑。我有一个相当简单的UITableViewCell子类。它为基本视图添加了一些额外的元素(通过[self.contentView addSubview:...]
并在元素上设置背景颜色,使它们看起来像黑色和灰色矩形框。
因为整个表格的背景具有这种具体的纹理图像,所以每个单元格的背景都需要是透明的,即使在选中时也是如此,但在这种情况下它应该会变暗。我已经设置了一个自定义的半透明选定背景来实现这个效果:
UIView *background = [[[UIView alloc] initWithFrame:self.bounds] autorelease];
background.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
background.opaque = NO;
[self setSelectedBackgroundView:background];
虽然这会产生正确的背景效果,但是当我选择细胞时会发生奇怪的副作用;所有其他背景都以某种方式转动关闭。这是一个截图。底部单元看起来应该并且未被选中。顶部单元格被选中,但它应该显示黑色和灰色矩形区域,但它们已经消失了!
谁知道这里发生了什么,更重要的是:我怎么能纠正这个?
答案 0 :(得分:53)
发生的事情是TableViewCell中的每个子视图都将接收setSelected和setHighlighted方法。 setSelected方法将删除背景颜色,但如果将其设置为选定状态,则会更正。
例如,如果这些是在自定义单元格中添加为子视图的UILabel,那么您可以将其添加到TableViewCell实现代码的setSelected方法中:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
self.textLabel.backgroundColor = [UIColor blackColor];
}
其中self.textLabel将是上面图片中显示的那些标签
我不确定您添加所选视图的位置,我通常会在setSelected方法中添加它。
或者,您可以继承UILabel并覆盖setHighlighted方法,如下所示:
-(void)setHighlighted:(BOOL)highlighted
{
[self setBackgroundColor:[UIColor blackColor]];
}
答案 1 :(得分:41)
如果您不知道发生了什么,单元格突出显示过程看起来很复杂且令人困惑。我彻底困惑,做了一些广泛的实验。以下是我的调查结果可能有助于某人的说明(如果有人有任何要添加或反驳请注释,我会尽力确认和更新)
处于正常的“未选择”状态
selectedBackgroundView
是HIDDEN backgroundView
可见(因此,如果您的contentView是透明的,则会看到backgroundView
或(如果您尚未定义backgroundView
,则会看到UITableView
的背景颜色1}}本身)选择了一个单元格,随后出现以下任何动画:
backgroundColor
(或设置为透明),标签等文本颜色更改为所选颜色selectedBackgroundView
变得可见(此视图始终是单元格的完整大小(忽略自定义框架,如果需要,请使用子视图)。另请注意backgroundColor
subViews
因某些原因不显示,也许它们像contentView
一样设置为透明。如果您没有定义selectedBackgroundView
,那么Cocoa将创建/插入蓝色(或灰色)渐变背景并为您显示此内容。backgroundView
未更改取消选择单元格后,将开始删除突出显示的动画:
selectedBackgroundView
alpha属性从1.0(完全不透明)动画到0.0(完全透明)。backgroundView
再次保持不变(因此动画看起来像selectedBackgroundView
和backgroundView
之间的交叉渐变)contentView
重新绘制在“未选中”状态,其子视图backgroundColor
再次可见(这可能会导致动画看起来很糟糕,所以它建议您不要在UIView.backgroundColor
)contentView
<强>结论:强>
如果您需要backgroundColor
来坚持突出显示动画,请不要使用backgroundColor
的{{1}}属性,而是可以尝试(可能在UIView
}):
具有背景颜色的CALayer:
tableview:cellForRowAtIndexPath:
或CAGradientLayer:
UIColor *bgColor = [UIColor greenColor];
CALayer* layer = [CALayer layer];
layer.frame = viewThatRequiresBGColor.bounds;
layer.backgroundColor = bgColor.CGColor;
[cell.viewThatRequiresBGColor.layer addSublayer:layer];
我还使用了CALayer.border技术来提供自定义UITableView分隔符:
UIColor *startColor = [UIColor redColor];
UIColor *endColor = [UIColor purpleColor];
CAGradientLayer* gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = viewThatRequiresBGColor.bounds;
gradientLayer.colors = @[(id)startColor.CGColor, (id)endColor.CGColor];
gradientLayer.locations = @[[NSNumber numberWithFloat:0],[NSNumber numberWithFloat:1]];
[cell.viewThatRequiresBGColor.layer addSublayer:gradientLayer];
答案 2 :(得分:17)
当您开始拖动UITableViewCell时,它会在其子视图上使用0-alpha颜色调用setBackgroundColor:
。我通过继承UIView并覆盖setBackgroundColor:
以忽略具有0-alpha颜色的请求来解决这个问题。它感觉很hacky,但它比any other solutions更清晰。
@implementation NonDisappearingView
-(void)setBackgroundColor:(UIColor *)backgroundColor {
CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor);
if (alpha != 0) {
[super setBackgroundColor:backgroundColor];
}
}
@end
然后,我向我的单元格添加NonDisappearingView
并向其添加其他子视图:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = @"cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
UIView *background = [cell viewWithTag:backgroundTag];
if (background == nil) {
background = [[NonDisappearingView alloc] initWithFrame:backgroundFrame];
background.tag = backgroundTag;
background.backgroundColor = backgroundColor;
[cell addSubview:background];
}
// add other views as subviews of background
...
}
return cell;
}
或者,您可以使cell.contentView成为NonDisappearingView
的实例。
答案 3 :(得分:5)
我的解决方案是保存backgroundColor
并在超级通话后恢复它。
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
UIColor *bgColor = self.textLabel.backgroundColor;
[super setSelected:selected animated:animated];
self.textLabel.backgroundColor = bgColor;
}
您还需要使用-setHighlighted:animated:
执行相同的操作。
答案 4 :(得分:4)
找到一个非常优雅的解决方案,而不是搞乱tableView方法。您可以创建UIView的子类,忽略将其背景颜色设置为清除颜色。代码:
Control
Obj-C版本类似,这里的主要内容是想法
答案 5 :(得分:2)
我创建了一个UITableViewCell类别/扩展,允许您打开和关闭此透明度&#34;功能&#34;。
通过将以下行添加到Podfile中,通过CocoaPods安装它:
pod 'KeepBackgroundCell'
<强>夫特强>
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
答案 6 :(得分:1)
通过阅读所有现有答案,通过仅对UITableViewCell进行子类化,使用Swift提出了一个优雅的解决方案。
extension UIView {
func iterateSubViews(block: ((view: UIView) -> Void)) {
for subview in self.subviews {
block(view: subview)
subview.iterateSubViews(block)
}
}
}
class CustomTableViewCell: UITableViewCell {
var keepSubViewsBackgroundColorOnSelection = false
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
// MARK: Overrides
override func setSelected(selected: Bool, animated: Bool) {
if self.keepSubViewsBackgroundColorOnSelection {
var bgColors = [UIView: UIColor]()
self.contentView.iterateSubViews() { (view) in
guard let bgColor = view.backgroundColor else {
return
}
bgColors[view] = bgColor
}
super.setSelected(selected, animated: animated)
for (view, backgroundColor) in bgColors {
view.backgroundColor = backgroundColor
}
} else {
super.setSelected(selected, animated: animated)
}
}
override func setHighlighted(highlighted: Bool, animated: Bool) {
if self.keepSubViewsBackgroundColorOnSelection {
var bgColors = [UIView: UIColor]()
self.contentView.iterateSubViews() { (view) in
guard let bgColor = view.backgroundColor else {
return
}
bgColors[view] = bgColor
}
super.setHighlighted(highlighted, animated: animated)
for (view, backgroundColor) in bgColors {
view.backgroundColor = backgroundColor
}
} else {
super.setHighlighted(highlighted, animated: animated)
}
}
}
答案 7 :(得分:0)
我们需要的是覆盖setSelected方法并在自定义tableViewCell类中更改tableViewCell的selectedBackgroundView。
我们需要在cellForRowAtIndexPath方法中为tableViewCell添加backgroundview。
lCell.selectedBackgroundView = [[UIView alloc] init];
接下来,我已经覆盖了如下所述的setSelected方法。
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
UIImageView *lBalloonView = [self viewWithTag:102];
[lBalloonView setBackgroundColor:[[UIColor hs_globalTint] colorWithAlphaComponent:0.2]];
UITextView *lMessageTextView = [self viewWithTag:103];
lMessageTextView.backgroundColor = [UIColor clearColor];
UILabel *lTimeLabel = [self viewWithTag:104];
lTimeLabel.backgroundColor = [UIColor clearColor];
}
另外需要注意的一点是更改tableViewCell选择样式。它不应该是UITableViewCellSelectionStyleNone。
lTableViewCell.selectionStyle = UITableViewCellSelectionStyleGray;