简体   繁体   English

UITableViewCell上的selectedBackgroundView被应用于单元格中的所有视图

[英]selectedBackgroundView on UITableViewCell gets applied to all views in cell

I have a table cell being displayed that shows a users image, name and some text. 我正在显示一个表格单元格,其中显示了用户图像,名称和一些文本。 The user's image is 50x50, but I want a border around it so I set the view to center the image and set the frame to 52x52 and then set the background color of that view to my border color. 用户的图像为50x50,但我希望在其周围有边框,因此我将视图设置为使图像居中并将框架设置为52x52,然后将该视图的背景色设置为我的边框颜色。 That shows a 1 pixel border around the image. 这表明图像周围有1个像素边框。

I also want to show a 30 pixel wide border on the right of the cell when the cell is selected. 选择单元格时,我还想在单元格的右侧显示30像素宽的边框。 I've tried to do that by creating a UIView the size of the cell's frame, then adding a subview to that view with a UIView the width and background color I would like. 我试图通过创建一个像单元格框架一样大小的UIView,然后向该视图添加一个子视图,并使用我想要的宽度和背景颜色的UIView来做到这一点。 I then set that view to the selectedBackgroundView of the cell. 然后,将该视图设置为单元格的selectedBackgroundView。

The problem here is that the cell's selectedBackgroundView gets applied to the background of all views inside the cell. 这里的问题是单元格的selectedBackgroundView应用于单元格内所有视图的背景。 So when I select a cell, the images "border" gets set to the cell's selected background color, the other 30px "border" I'm adding gets changed to that background color also. 因此,当我选择一个单元格时,图像“边框”将设置为该单元格的所选背景色,我添加的其他30px“边框”也将更改为该背景色。

Code inside my cellForRowAtIndexPath: 我的cellForRowAtIndexPath内部的代码:

cell = (UserCellView *) currentObject;

UIView *c = [[UIView alloc ] initWithFrame:CGRectMake(0, 0, 30, cell.frame.size.height)];
c.backgroundColor = [[UIColor alloc] initWithRed:64/255.0 green:64/255.0 blue:64/255.0 alpha:1.0];

UIView *v = [[UIView alloc ] initWithFrame:cell.frame];             
v.backgroundColor = [[UIColor alloc] initWithRed:35/255.0 green:35/255.0 blue:35/255.0 alpha:1.0];              

[v addSubview:c];       

cell.selectedBackgroundView = v;

[c release];
[v release];

I'll assume that you haven't actually tested what's going on to form your analysis that it "gets applied to the background of all views inside the cell". 我假设您尚未实际测试构成“将其应用于单元格中所有视图的背景”的分析的结果。

I did something like this: 我做了这样的事情:

@interface TestView : UIView {
}
@end
@implementation TestView
-(void)setBackgroundColor:(UIColor*)c {
  // Breakpoint here.
  NSLog("setBackgroundColor: %@",c);
  [super setBackgroundColor:c];
}
@end

...

UIView * v = [[[UIView alloc] initWithFrame:(CGRect){{0,0},{20,20}}] autorelease];
v.backgroundColor = [UIColor magentaColor];
UIView * v2 = [[[TestView alloc] initWithFrame:(CGRect){{5,5},{10,10}}] autorelease];
v2.backgroundColor = [UIColor yellowColor];
[v addSubview:v2];
cell.selectedBackgroundView = v;

The end result is that -setBackgroundColor: is called from -[UITableViewCell _setOpaque:forSubview:] when the view is selected, with something like UIDeviceWhiteColorSpace 0 0 (ie [UIColor clearColor] ). 最终的结果是, -setBackgroundColor:从称为-[UITableViewCell _setOpaque:forSubview:]当视图被选择时,与像UIDeviceWhiteColorSpace 0 0 (即[UIColor clearColor]

Or, in other words, the background colour of some of the subviews are set to [UIColor clearColor] while the cell is selected, allowing selectedBackgroundView to show through. 或者,换句话说,在选定单元格时,某些子视图的背景色设置为[UIColor clearColor] ,从而允许selectedBackgroundView显示出来。 I think this happens because a common optimization is to give textLabel / detailTextLabel the table's background colour (eg white) so it draws faster, but this means the background colour has to be reset when the cell is selected. 认为发生这种情况是因为常见的优化方法是为textLabel / detailTextLabel表格的背景颜色(例如白色),以便绘制速度更快,但这意味着在选择单元格时必须重置背景颜色。

The easiest fix is to use an image instead: a 1-by-1-pixel image of the correct colour in a UIImageView will work, if a bit messy. 最简单的解决方法是改为使用图像:如果有点混乱,则可以在UIImageView中使用正确颜色的1 x 1像素图像。 (I had this problem when drawing custom separator lines with 1-pixel-high UIViews, so I just included the separator into the background image.) (在用1像素高的UIView绘制自定义分隔线时遇到了这个问题,因此我只是将分隔线包括在背景图像中。)

An alternative fix is to use a CALayer instead: Add a 52x52 sublayer to the UIImageView's layer, and set the sublayer's background colour. 另一种解决方法是改用CALayer:在UIImageView的图层中添加52x52子图层,并设置子图层的背景色。 I'm pretty sure UITableViewCell simply walks the view hierarchy, so it should ignore custom layers. 我很确定UITableViewCell只会遍历视图层次结构,因此它应该忽略自定义图层。 (The big disadvantage with layers is that they don't auto-size, which made them unsuitable for my purposes, and means the 30px right border won't auto-size.) (图层的最大缺点是它们不会自动调整大小,这使它们不适合我的用途,并且意味着30px的右边框不会自动调整大小。)

A workaround is to subclass the relevant views and ignore -setBackgroundColor: if it's equal to [UIColor clearColor] . 一种解决方法是对相关视图进行子类化,如果-setBackgroundColor:等于[UIColor clearColor]则将其忽略。

A simple but obnoxious-to-maintain solution is to override setSelected:animated: and setHighlighted:animated: with implementations re-setting the various backgrounds you want. 一个简单但令人讨厌的解决方案是重写setSelected:animated:和setHighlighted:animated:,并通过实现重新设置所需的各种背景。 Something along the lines of: 类似于以下内容:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    self.childView.backgroundColor = [UIColor blueColor]; // whichever you want
}

First add this to your file 首先将此添加到您的文件

#import <QuartzCore/QuartzCore.h>

Then turn your view into an image with... 然后将您的视图变成具有...的图像

    UIView *rowView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1.0, 60.0)];
    rowView.backgroundColor = [UIColor colorWithRed:35/255.0 green:35/255.0 blue:35/255.0 alpha:1.0];        

    UIGraphicsBeginImageContext(rowView.bounds.size);
    [rowView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *yourImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

Then instead of adding a UIView to your cell, just add a UIImageView with "yourImage". 然后,无需将UIView添加到您的单元中,只需添加带有“ yourImage”的UIImageView。

A simple solution if the affected view can be a custom subclass is to override -setBackgroundColor: 如果受影响的视图可以是自定义子类,一个简单的解决方案是重写-setBackgroundColor:

- (void)setBackgroundColor:(UIColor *)color
{
    // Ignore requests and do nothing
}

Thus UITableViewCell 's attempt to set the colour will go ignored. 因此, UITableViewCell设置颜色的尝试将被忽略。 Code in the custom view which really does want to set the background colour needs to call super : 确实希望设置背景颜色的自定义视图中的代码需要调用super

- (void)setColor:(UIColor *)color
{
    [super setBackgroundColor:color];
}

(or could probably message the underlying CALayer directly) (或者可能直接向基础CALayer发送消息)

you will need to customize the contentView of the cells and handle the delegate tableView:cellForRowAtIndexPath 您将需要自定义单元格的contentView并处理委托tableView:cellForRowAtIndexPath

See Posting Here 请参阅此处发布

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM