4
votes

So in my custom view, I'm trying to draw a white/gray gradient using Core Graphics. I have the following code:

UIColor *color1 = [UIColor whiteColor];
UIColor *color2 = [UIColor colorWithRed:209.0/255.0 green:212.0/255.0 blue:217.0/255.0 alpha:1.0];

CFMutableArrayRef colors = CFArrayCreateMutable(NULL, 0, NULL);
CFArrayAppendValue(colors, color1.CGColor);
CFArrayAppendValue(colors, color2.CGColor);

CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[2] = {0.0, 1.0};
CGGradientRef gradient = CGGradientCreateWithColors(colorspace, colors, locations);

CGContextDrawLinearGradient(UIGraphicsGetCurrentContext(), gradient, topCenter, bottomCenter, kCGGradientDrawsAfterEndLocation);

I think this code is fairly straightforward and should result in a nice white/gray gradient. But it doesn't; it draws a transparent/gray gradient.

I think it may have something to do with the view's background color, which is [UIColor clearColor]. But I cannot change that, as I need to have some portions of my view to be transparent.

Any ideas?

2
Look at this stackoverflow.com/questions/3060010/… It seems related, but not the exact question, so don't want to mark as a duplicate. - Lou Franco
When you change the background color to white color from clear color do things look right? - Zigglzworth
Yes, but unfortunately that's not an option for me - Rits
I read the other question and indeed, it appears to be an issue with the color space. I changed CGColorSpaceCreateDeviceRGB() to CGColorSpaceCreateDeviceGray() and that worked; the white color is correctly displayed now. But doesn't this mean that only gray colors are displayed? And how can I solve that? - Rits

2 Answers

4
votes
UIColor *color1 = [UIColor whiteColor];

The above line likely creates a color in the greyscale colorspace.

Try this instead:

UIColor *color1 = [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:1.f];
4
votes

UIColors can result to colors defined in different color space. White will be a monochrome color.

This code demonstrates, how to deal with it.

CGColorSpaceRef fillColorSpace = CGColorGetColorSpace([self.fillColor CGColor]);
const float* fillColors = CGColorGetComponents([self.fillColor CGColor]);

if (CGColorSpaceGetModel(fillColorSpace) == kCGColorSpaceModelRGB) {
    CGContextSetRGBFillColor(contextRef, fillColors[0],fillColors[1], fillColors[2], fillColors[3]);
} else if (CGColorSpaceGetModel(fillColorSpace) == kCGColorSpaceModelMonochrome){
    CGContextSetGrayFillColor(contextRef, fillColors[0], fillColors[1]);
}

You can use this approach to convert monochrome colors to RGB colors as-well:

if (CGColorSpaceGetModel(fillColorSpace) == kCGColorSpaceModelMonochrome){
        const float* colors = CGColorGetComponents([self.fillColor CGColor]);
        self.fillColor = [UIColor colorWithRed:colors[0]  
                                         green:colors[0]  
                                          blue:colors[0] 
                                         alpha:colors[1]];
}

Now the color is RGB, so you don't need to distinguish between CG functions for different color models.

const float* fillColors = CGColorGetComponents([self.fillColor CGColor]);
CGContextSetRGBFillColor(contextRef, fillColors[0],fillColors[1], fillColors[2], fillColors[3]);