Reputation: 8977
So I am trying to override drawRect in my UIScrolLView, however it gives me this black background instead of the background color that I've specified for my UIScrollView. Why is this? If I remove the drawRect code then everything is fine:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
if (shouldDrawVerticalLineForProfile){
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorRef separatorColor = [UIColor colorWithRed:47.0/255.0 green:47.0/255.0
blue:47.0/255.0 alpha:1.0].CGColor;
// Add at bottom
CGPoint startPoint = CGPointMake(60, 0);
CGPoint endPoint = CGPointMake(60, 10000);
CGContextSaveGState(context);
CGContextSetLineCap(context, kCGLineCapSquare);
CGContextSetStrokeColorWithColor(context, separatorColor);
CGContextSetLineWidth(context, 5.0);
CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5);
CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
}
Upvotes: 22
Views: 13824
Reputation: 1972
The answer here is very clearly documented in the AppleDocs for UIView's drawRect:
method. The first sentence is:
The default implementation of this method does nothing.
So, the suggestions here to call super are not going to help. The rest of the answer is contained further down in the discussion:
... if the opaque property of your view is set to YES, your drawRect: method must totally fill the specified rectangle with opaque content.
Meaning that if you don't intend to have a transparent background, you need to actually draw the background. The most correct way to do this is to use the following drawRect:
template:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect]; // optional if a direct UIView-subclass, should be called otherwise.
CGContextRef context = UIGraphicsGetCurrentContext();
// Fill the background color, if needed
if (self.opaque) {
UIGraphicsPushContext(context);
CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor);
CGContextFillRect(context, rect);
UIGraphicsPopContext();
}
// Your code here...
}
Swift Update
Since you are responsible to add background color on your custom view, make sure to fill rect with color:
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else {
return
}
context.saveGState()
// Add you custom color
context.setFillColor(UIColor.white.cgColor)
context.fill(rect)
defer { context.restoreGState() }
// Your custom drawing ....
}
By the way, you could also set your custom view background color on init
. Then you do not need to fill rect with color as stated above.
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.white
}
Upvotes: 11
Reputation: 1931
Please try this its Work for me
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setBackgroundColor:[UIColor clearColor]];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
if (shouldDrawVerticalLineForProfile){
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorRef separatorColor = [UIColor colorWithRed:47.0/255.0 green:47.0/255.0
blue:47.0/255.0 alpha:1.0].CGColor;
// Add at bottom
CGPoint startPoint = CGPointMake(60, 0);
CGPoint endPoint = CGPointMake(60, 10000);
CGContextSaveGState(context);
CGContextSetLineCap(context, kCGLineCapSquare);
CGContextSetStrokeColorWithColor(context, separatorColor);
CGContextSetLineWidth(context, 5.0);
CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5);
CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
}
Upvotes: 4
Reputation: 829
The only thing that worked for me was to explicitly set the background after any call to setNeedsDisplay
. In my example, I was using a subclass of an MKAnnotationView
over a map, instead of a UIScrollView
, so I don't really know how well this applies to the OP scenario. In my case, I was calling setNeedsDisplay
from setAnnotation
, and I found that doing so resets by backgroundColor
. Simply re-setting by backgroundColor
after setNeedsDisplay
fixes the problem.
FWIW, I too observed that simply overriding drawRect
to delegate to the super class caused this black background problem.
Upvotes: -1
Reputation: 345
I ran into a similar situation when overriding drawRect in my UIScrollView subclass.
Simply overriding with:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
}
resulted in a black background instead of the desired clear background I'd get without overriding.
I found it was because the View Background was set to Default in Interface Builder and that setting it to Clear Color
resolved the issue for me.
I'm not sure if this is related to your problem but thought I'd share in case it might help.
Upvotes: 14
Reputation: 2498
I guess what you are searching for is:
myScrollViewInstance.opaque = NO
After that the background of your scroll view should not be black anymore.
Upvotes: 23
Reputation: 3054
This should help
CGContextSetFillColorWithColor(context, colorBack);
CGContextFillRect(context, self.bounds);
// Choose bounds and colorBack accordingly
Upvotes: 4