views:

70

answers:

4

I'm trying to make a subclassed UITableViewCell where I draw an image in the upper right corner. I have it working perfectly - except when I set self.backgroundView, my background image covers up the image drawn in drawRect.

There must be a way to be able to set a background image (and the selectedBackgroundView) without covering up what's being done in drawRect.

Am I going about this the wrong way?

EDIT: I've posted an 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)];
}
A: 

Have you tried adding a [super drawRect:rect]; there?

St3fan
I just tried adding it, but it had no effect. I appreciate the suggestion though.
Jawboxer
+2  A: 

You shouldn't override the -drawRect: of a tablecell. Instead, create a new custom view and add it to the cell's contentView, and draw in there.

Ben Gottlieb
The problem with doing that, is if I swipe to delete the cell, the delete button pushes my "star corner" image to the left - which is why I ended up trying to use drawRect. I'll play around with that some more though, in case I missed something. Thanks.
Jawboxer
+2  A: 

You are not really supposed to mix the drawing with your cell like that, you are operating at a lower-level than the UITableViewCell machinery is operating, and this is why you get this problem.

This is just one of the various problems you will end up running into. You will run into other problems as you go down that path, including problems with how the selection works.

The proper approach is to create a custom UIView that contains the code to draw, and then you can addSubView that into your cell's root view. That will take care of the rendering in the proper order, and wont interfere with the selection system, and will work correctly in this case.

miguel.de.icaza
By "cell's root view", do you mean cell.contentView? When I've tried a custom UIView (or UIImageView) I have problems with the cell's delete button pushing the view over to the left. I'm using UIViewAutoresizingFlexibleLeftMargin on the custom view since I'm trying to support landscape mode, and want that star corner image to always be fixed to the upper right corner of the cell. (plus I need to support editing mode and reordering).
Jawboxer
Make sure that your view supports the resizing protocol by implementing the layoutSubviews method of UIView class. This method will be invoked with the new size if the UI rotates, or if editing is taking place. Just adjust any subviews bounds or frames there.
miguel.de.icaza
I figured out how to do it without subclassing the UITableViewCell. All I needed was to create an ImageView with the star, then add that as a subview to an ImageView with the cell background image - and finally assign that to my cell.backgroundView (not the contentView). So, thank you and Ben for steering me away from the drawRect solution and pointing me back in the right direction. I learned a lot, and now it seems easy in retrospect.
Jawboxer
A: 

Here's a solution that's a bit of a kludge, but it fits my requirements exactly... with one fatal flaw: when cells get reused, the star corner shows up when I don't want it to.

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

I'm still using drawRect here, but only because self.starImage is null if you access it within the initWithStyle method. Also, instead of adding the subview to self.contentView, I'm adding it to self.backgroundView to prevent the cell's delete button from interfering with it. The star corner is positioned correctly in both portrait and landscape mode, and works fine within edit mode as well.

With the cell reuse issue though, It's still a no go... so, maybe I'm back to trying to do it without subclassing UITableViewCell.

I'm open to any further suggestions. Thank you!

- (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];
}
Jawboxer