-->

UIView subclass draws background despite completel

2020-08-17 12:27发布

问题:

So, I have a custom UIView subclass which enables drawing of rounded edges. The thing draws perfectly, however the background always fills the whole bounds, despite clipping to a path first. The border also draws above the rectangular background, despite the fact that I draw the border in drawRect: before the background. So I removed the whole content of drawRect:, which is now virtually empty - nevertheless the background gets drawn!

Anybody an explanation for this? I set the backgroundColor in Interface Builder. Thanks!

回答1:

Sorry for this monologue. :)

The thing is that the UIView's layer apparently draws the background, which is independent from drawRect:. This is why you can't get rid of the background by overriding drawRect:.

You can either override - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx and make the layer draw whatever you want, or you override - (void) setBackgroundColor:(UIColor *)newColor and don't assign newColor to backgroundColor, but to your own ivar, like myBackgroundColor. You can then use myBackgroundColor in drawRect; to draw the background however you like.


Overriding setBackgroundColor:

Define an instance variable to hold your background color, e.g. myBackgroundColor. In your init methods, set the real background color to be the clearColor:

- (id) initWithCoder:(NSCoder *)aDecoder
{
    if ((self = [super init...])) {
        [super setBackgroundColor:[UIColor clearColor]];
    }
    return self;
}

Override:

- (void) setBackgroundColor:(UIColor *)newColor
{
    if (newColor != myBackgroundColor) {
        [myBackgroundColor release];
        myBackgroundColor = [newColor retain];
    }
}

Then use myBackgroundColor in your drawRect: method. This way you can use the color assigned from Interface Builder (or Xcode4) in your code.



回答2:

Here's an easier fix:

self.backgroundColor = [UIColor clearColor];


回答3:

I hesitate to suggest this because I don't want to offend you, but have you set opaque to NO?



回答4:

This is easily reproducible:

Create a new View-Based iPhone Application. Create an UIView subclass and leave the drawRect: method completely empty. In Interface Builder, drag a UIView into the main view, assign it a background color and set the class of the view to your subclass. Save, build and run, and see, the view shows the background color.

I have circumvented this behaviour by overriding setBackgroundColor: and assigning the color to my own ivar, always leaving the backgroundColor property nil. This works, however I'm still wondering why this works this way.



回答5:

You should set

clearsContextBeforeDrawing = NO

It's that simple.

From the UIView Reference Docs

Oops. I misunderstood the question. The OP (original poster) wants their custom control to support the standard "backgroundColor" property (eg, set by the gui designer), but does NOT want the system to paint that color. The OP wants to paint the bg himself so that he can round the corners.

In that case, the post about overriding the layer level drawing is correct.

The solution I posted will prevent the UI system from clearing your buffer before drawing. When you have no bg defined, if clearsContextBeforeDrawing is set, the iOS will clear your view's buffer, setting all pixels to transparent black. Doing this for a full-screen view takes about 5ms in an iPad3, so it's not free (pushing that 2048x1536 pixels never is). For comparison drawing a full-screen bitmap (using kCGBlendModeCopy to force blitting) takes ~25ms (using quartz, not GPU).