2
votes

This is what it looks like. I want to make the black background Clear and can't seem to figure it out.

enter image description here

Here is the loadView:

loadView { 
  CGRect frame = CGRectMake(screenWidth - OFFSET, DEFAULT_PADDING, 140, 40);
  miniC* mcView = [ [ [miniC alloc] initWithFrame:frame] autorelease];
  mcView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
  [[self view] addSubview:mcView]; 
}

Here is where I drawRect I call in miniC:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Set Background Color & Border Color
    CGColorRef bgColor = [UIColor scrollViewTexturedBackgroundColor].CGColor; 
    CGColorRef borderColor = [UIColor grayColor].CGColor; 

    CGRect Rect = self.bounds;

    // Round Corners
    roundCorners(context, Rect);

    // Fill with bgcolor
    fillBackgroundColor(context, Rect, bgColor);

    // Add 1 px stroke
    CGRect strokeRect = Rect;
    strokeRect.size.height -= 1;
    strokeRect = (strokeRect);

    CGContextSetStrokeColorWithColor(context, borderColor);
    CGContextSetLineWidth(context, 1.0);
    CGContextStrokeRect(context, strokeRect);


    // Overlay Rect to Tint "scrollViewTexturedBackgroundColor" UIColor
    CGContextRef secondContext = UIGraphicsGetCurrentContext();

    // Set Background Color & Border Color
    CGColorRef obgColor = [UIColor colorWithRed:255/255 green:255/255 blue:255/255 alpha:.3].CGColor; 

    // Round Corners
    roundCorners(context, Rect);

    // Fill with bgcolor
    fillBackgroundColor(secondContext, Rect, obgColor);

}

The code draws the the rounded box with a stroke I am looking for but there is a black box behind the new rounded box. I've been trying a bunch of different stuff but can't seem to figure out how to make the background color clear. Also, I am aware I could do this with QuartzCore but I do not want to.

P.S. I am new to objective-c.

EDIT:

void roundCorners(CGContextRef context, CGRect rect) {

CGContextClearRect(context, rect);

CGFloat c = INSET + CORNER_RADIUS;

CGContextMoveToPoint(context, INSET, c);

CGContextAddArcToPoint(context, INSET, INSET, c, INSET, CORNER_RADIUS);    
CGContextAddLineToPoint(context, rect.size.width - c, INSET);
CGContextAddArcToPoint(context, rect.size.width - INSET, INSET, rect.size.width - INSET, c, CORNER_RADIUS);
CGContextAddLineToPoint(context, rect.size.width - INSET, rect.size.height - c);
CGContextAddArcToPoint(context, rect.size.width - INSET, rect.size.height - INSET, rect.size.width - c, rect.size.height -

INSET, CORNER_RADIUS); CGContextAddLineToPoint(context, c, rect.size.height - INSET);

CGContextAddArcToPoint(context, INSET, rect.size.height - INSET, INSET, rect.size.height > - c, CORNER_RADIUS);

CGContextClosePath(context);

CGContextClip(context);

CGContextSetFillColorWithColor(context, [UIColor scrollViewTexturedBackgroundColor].CGColor);
CGContextFillRect(context, CGRectMake(0, 0, rect.size.width - INSET, rect.size.height - INSET));

}

void fillBackgroundColor(CGContextRef context, CGRect rect, CGColorRef bgColor) {

CGContextSetFillColorWithColor(context, bgColor);
CGContextFillRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height));

}

2
Did you remember to make the view non-opaque?Firoze Lafeer
Definitely did not. Where would I set this?morcutt
You can add 'mcView.opaque = NO' to your loadView just to be sure that's it. And then if that was the only issue, move it to the initWithFrame which Paul s. wrote out for you.Firoze Lafeer
That's strange. Just to check, I copied and pasted your code and it works just fine for me. So it must be something in code that is not here in your question. What is here works and gives me a nice rounded rectangle with a linen type fill and no black backgroundFiroze Lafeer
If you're doing more with this view than what you've shown here, I would suggest you comment that stuff out. Boil it down to just this, which you'll see works, and then build up again from there. That usually works for me. Good luck!Firoze Lafeer

2 Answers

5
votes

You need to set the background color of your UIView

e.g.

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}   

Some other stuff for consideration especially as you say your new to the language etc.

This assignment CGRect Rect = self.bounds; is superflous as you are being passed rect in as a method argument so you can remove this.

The name CGRect Rect for a variable is not great in Objective-C as things that start with a capital letter are normally constants so this may be confusing and cause some issues later on.

This assignment strokeRect = (strokeRect); is superflous, this does the job just fine on it's own strokeRect.size.height -= 1;

I could be wrong I'm no core graphics expert but I am assuming this CGContextRef secondContext = UIGraphicsGetCurrentContext(); will return the same context you had before.

1
votes

CGContextClearRect is very tricky. Since your context comes to you empty, you should not use it unless you have to. If you do use it, the important thing is that your view's backgroundColor should not be a 100% opaque color: its alpha must be less than 1. Otherwise, it paints black (as you are seeing) instead of transparent.

You are showing way too much code, so you're just confusing yourself and making life difficult for those who want to help you. It is best to start with something very simple as a proof of concept. Here's an extremely simple view that paints itself as a round rect using CGContextClearRect and clipping:

- (void) configure {
    self.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:.99];
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self configure];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder 
{
    self = [super initWithCoder: aDecoder];
    if (self) {
        [self configure];
    }
    return self;
}

- (void) drawRect: (CGRect) rect {
    CGContextRef con = UIGraphicsGetCurrentContext();
    CGPathRef p = [[UIBezierPath bezierPathWithRoundedRect:rect 
                                              cornerRadius:10] CGPath];
    CGContextAddRect(con, rect);
    CGContextAddPath(con, p);
    CGContextEOClip(con);
    CGContextClearRect(con, rect);
}

The result is a red rounded-rect. But... Change .99 to 1 in the first line, and the corners of the view come out black, just as in your picture! This shows the importance of a non-opaque view background color when you use CGContextClearRect. (I regard this as a bug, but that's neither here nor there; it's been this way for a very long time and I don't expect things to change.)