子类 UITableViewCell - backgroundView 涵盖了我在 drawRect 中所做的任何事情

Posted

技术标签:

【中文标题】子类 UITableViewCell - backgroundView 涵盖了我在 drawRect 中所做的任何事情【英文标题】:subclassed UITableViewCell - backgroundView covers up anything I do in drawRect 【发布时间】:2010-08-20 03:12:20 【问题描述】:

我正在尝试创建一个子类 UITableViewCell,我在右上角绘制图像。我让它工作得很好 - 除了我设置 self.backgroundView 时,我的背景图像覆盖了在 drawRect 中绘制的图像。

必须有一种方法可以设置背景图像(和 selectedBackgroundView),而不会掩盖在 drawRect 中所做的事情。

我是不是走错了路?

编辑:我已经发布了example project with the problem。

    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 

    if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) 

     // TODO: figure out why this covers up self.starImage that's drawn in drawRect
         self.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cellBackground.png"]] autorelease];
    
    return self;


- (void)drawRect:(CGRect)rect 
    [self.starImage drawAtPoint:CGPointMake(self.bounds.size.width - self.starImage.size.width, 0.0)];


编辑 2:应 AWrightIV 的要求,这就是我如何让它工作的……它根本不需要子类化 UITableViewCell。我只是在 cell.backgroundView 中添加一个子视图:

// create a UIImageView that contains the background image for the cell
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cellBackground.png"]];

// create another UIImageView that contains the corner image
UIImage *starRedImage = [UIImage imageNamed:@"starcorner_red.png"];
UIImageView *starImageView = [[UIImageView alloc] initWithFrame:CGRectMake(297,
                                                                               0,
                                                                               starRedImage.size.width,
                                                                               starRedImage.size.height)];
starImageView.image = starRedImage;

// add the corner UIImageView as a subview to the background UIImageView
[bgImageView addSubview:starImageView];

// set cell.background to use the background UIImageView
cell.backgroundView = bgImageView;

【问题讨论】:

【参考方案1】:

您不应该像那样将绘图与您的单元格混合,您的操作级别低于 UITableViewCell 机器的操作级别,这就是您遇到此问题的原因。

这只是您最终会遇到的各种问题之一。当你沿着这条路走下去时,你会遇到其他问题,包括选择如何工作的问题。

正确的方法是创建一个包含要绘制的代码的自定义 UIView,然后您可以将其添加到单元格的根视图中。这将以正确的顺序处理渲染,并且不会干扰选择系统,并且在这种情况下可以正常工作。

【讨论】:

“单元格的根视图”是指 cell.contentView 吗?当我尝试自定义 UIView(或 UIImageView)时,我遇到了单元格的删除按钮将视图推到左侧的问题。我在自定义视图上使用 UIViewAutoresizingFlexibleLeftMargin ,因为我试图支持横向模式,并希望该星角图像始终固定在单元格的右上角。 (另外我需要支持编辑模式和重新排序)。 通过实现 UIView 类的 layoutSubviews 方法,确保您的视图支持调整大小协议。如果 UI 旋转或正在编辑,将使用新大小调用此方法。只需在那里调整任何子视图边界或框架。 我想出了如何在不继承 UITableViewCell 的情况下做到这一点。我只需要创建一个带有星形的 ImageView,然后将其作为子视图添加到带有单元格背景图像的 ImageView - 最后将其分配给我的 cell.backgroundView(而不是 contentView)。所以,谢谢你和 Ben 引导我远离 drawRect 解决方案,并让我回到正确的方向。我学到了很多,现在回想起来似乎很容易。 @Jawboxer 有什么方法可以发布您的新代码,以便我们将其与您的原始代码进行比较?我知道它已经一年了,所以如果它被埋没了,不用担心。 @AWrightIV 我编辑了问题以添加我用来让它工作的代码。 (基本上是按照 Miguel 和 Ben 的建议)【参考方案2】:

您不应该覆盖表格单元的 -drawRect:。相反,创建一个新的自定义视图并将其添加到单元格的 contentView 中,然后在其中绘制。

【讨论】:

这样做的问题是,如果我滑动删除单元格,删除按钮会将我的“星角”图像推向左侧——这就是我最终尝试使用 drawRect 的原因。不过,我会再玩一些,以防我错过了什么。谢谢。【参考方案3】:

您是否尝试在此处添加[super drawRect:rect];

【讨论】:

我刚刚尝试添加它,但它没有效果。不过我很欣赏这个建议。【参考方案4】:

这是一个有点杂乱无章的解决方案,但它完全符合我的要求……有一个致命缺陷:当单元被重复使用时,星角会在我不希望出现时出现。

http://dl.dropbox.com/u/2349787/UIImage_Position_subclassed_cell2.zip

我在这里仍然使用 drawRect,但只是因为如果您在 initWithStyle 方法中访问 self.starImage 为 null。此外,我没有将子视图添加到 self.contentView,而是将其添加到 self.backgroundView 以防止单元格的删除按钮干扰它。星角在纵向和横向模式下都正确定位,在编辑模式下也能正常工作。

虽然有单元重用问题,但仍然不行......所以,也许我会重新尝试在不继承 UITableViewCell 的情况下这样做。

我愿意接受任何进一步的建议。谢谢!

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
    if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) 
        // Initialization code

        self.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cellBackground.png"]] autorelease];
    
    return self;


- (void) drawRect:(CGRect)rect 

    UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(self.bounds.size.width - self.starImage.size.width, 0, self.starImage.size.width, self.starImage.size.height)] autorelease];
    imageView.image = self.starImage;
    imageView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;

    [self.backgroundView addSubview:imageView];

【讨论】:

drawRect: 内部调用addSubview: 不是一个好主意,因为drawRect: 会被调用多次。

以上是关于子类 UITableViewCell - backgroundView 涵盖了我在 drawRect 中所做的任何事情的主要内容,如果未能解决你的问题,请参考以下文章

子类化 UItableViewCell 选择

绘图 + UITableViewCell + UIScrollView 子类?

为啥我必须删除为 UITableViewCell 添加的子视图,而不是在 UITableViewCell 的子类中?

使用故事板和子类自定义 UITableViewCell

持久化 UITableViewCell 子类属性

子类化 UITableViewCell 不适用于出队