Black to White radial gradient is giving whole black screen - ios

It should be very simple to create a black to white radial gradient using Core Graphics, but even after many tries I am not able to figure where I am going wrong.
I want something like this:
This is my code:
CGFloat radius = shapeRect.size.width/2.0;
CGPoint center = CGPointMake(shapeRect.origin.x+shapeRect.size.width/2, shapeRect.origin.y+shapeRect.size.height/2);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(NULL, shapeRect.size.width, shapeRect.size.height, 8, shapeRect.size.width*4, colorSpace, kCGImageAlphaNone);
CGFloat components[] = {0.0, 1.0};
CGFloat locations[] = {0.0, 1.0};
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);
CGContextDrawRadialGradient(context, gradient, center, 10, center, radius, 0);
CGImageRef img = CGBitmapContextCreateImage(context);
[maskedView setImage:[UIImage imageWithCGImage:img]];
CGGradientRelease(gradient);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
ShapeRect here has self.view bounds.
I am getting a whole black screen with no gradient as output.
I am using iPhone 7 simulator.
Your suggestions can save my day
Thank you.

Please check this snippet. You can change components and locations values to get what you want and to understand how the drawing works. Refer to CGGradientCreateWithColorComponentsdescription
#import "TestView.h"
#implementation TestView {
CGGradientRef _gradient;
}
-(void)drawRect:(CGRect)rect
{
CGFloat radius = self.frame.size.width / 2.0;
CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
CGContextRef context = UIGraphicsGetCurrentContext();
CGGradientRef gradient = [self createGradient];
CGContextDrawRadialGradient(context, gradient, center, 10, center, radius, kCGGradientDrawsBeforeStartLocation);
}
-(CGGradientRef)createGradient
{
if (!_gradient) {
CGFloat components[] = { 0.0, 1.0, 0.5, 0.5, 1.0, 0.3 };
CGFloat locations[] = { 0.0, 0.6, 1.0 };
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
_gradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 3);
CGColorSpaceRelease(colorSpace);
}
return _gradient;
}
- (void)layoutSubviews
{
self.backgroundColor = [UIColor whiteColor];
self.layer.borderColor = [UIColor lightGrayColor].CGColor;
self.layer.borderWidth = 1.;
}
#end
Result:

Related

Changing colors of drawRect

I drew a line using drawRect. Now I want to change the color of it.
Example Code: self.pattern.backgroundColor = [UIColor clearColor];
I need to be able to change the color of the drawRect like that code. I get stuck on the second part of the code.
self. ? . backgroundColor: The questions marks is where i get stuck. What should I put there for a drawRect?
Here is some code from my drawRect too:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// Setup background
//CGFloat components1[] = {0.0, 0.0, 0.0, 1.0};
//CGColorSpaceRef colorspace1 = CGColorSpaceCreateDeviceRGB();
////CGColorRef black = CGColorCreate(colorspace1, components1);
//CGContextSetFillColorWithColor(context,black);
//CGContextSetRGBFillColor(context,0.0,0.0,0.0,1.0);
// 1 pixel: iphone 6 the point = 0.5 and 6 plus = 0.333333;
//CGFloat point =1.f/[UIScreen mainScreen].scale;
CGFloat point =width/[UIScreen mainScreen].scale;
CGContextSetLineWidth(context,point);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat red [] = {1.0, 0.0, 0.0, 1.0}; // green
CGFloat green [] = {0.0, 1.0, 0.0, 1.0}; // green
CGColorRef color = CGColorCreate(colorspace, green);
CGContextBeginPath(context);
if(bFirstLine && bAlter)
{
CGColorRef colorR = CGColorCreate(colorspace, red);
CGContextSetStrokeColorWithColor(context, colorR);
}
}
[[UIColor redColor] setFill]; // to set the color for fillings
[[UIColor redColor] setStroke]; // to set the color for strokes
and in your case (if i got you right):
[self.backgroundColor setFill];
[self.backgroundColor setStroke];

Drawing Circular Gradient

I would like to draw a circular gradient like in the example picture below. I can manage a radial gradient easily but I am not sure how to do a circular one.
I was thinking of drawing a gradient on a line and then transforming it to a circle. Would that be possible?
This is how I draw the radial gradient:
CGFloat a = MIN(self.frame.size.width, self.frame.size.height) - _lineWidth;
//Get current context
CGContextRef mainContext = UIGraphicsGetCurrentContext();
CGRect newRect = rect;
newRect.origin.x = ((self.frame.size.width - a)/2.0f);
newRect.origin.y = ((self.frame.size.height - a)/2.0f);
newRect.size.width = a;
newRect.size.height = a;
// Fill circle
const CGFloat *_components = CGColorGetComponents(_fillColor.CGColor);
CGFloat red = _components[0];
CGFloat green = _components[1];
CGFloat blue = _components[2];
CGFloat alpha = _components[3];
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGFloat redBallColors[] = {
red,green,blue,0.5,
red,green,blue,alpha,
};
CGFloat glossLocations[] = {0.0, 1.0};
CGGradientRef ballGradient = CGGradientCreateWithColorComponents(baseSpace, redBallColors, glossLocations, 2);
CGPoint startPoint = self.center;
CGPoint endPoint = self.center;
CGContextDrawRadialGradient(mainContext, ballGradient, startPoint, 0, endPoint, a/2, 0);
Thanks a lot!

Can't get CGGradientRef to work with alpha

I am trying to apply an alpha gradient to a UIView but can't get it to work at all. My current drawRect: method looks like this -
- (void)drawRect:(CGRect)rect
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGGradientRef alphaGradient;
CGColorSpaceRef rgbColorSpace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 1.0, // Start color
1.0, 1.0, 1.0, 0.0 }; // End color
rgbColorSpace = CGColorSpaceCreateDeviceRGB();
alphaGradient = CGGradientCreateWithColorComponents(rgbColorSpace, components, locations, num_locations);
CGRect currentBounds = self.bounds;
CGPoint bottomCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMaxY(currentBounds));
CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds));
CGContextDrawLinearGradient(currentContext, alphaGradient, midCenter, bottomCenter, 0);
CGGradientRelease(alphaGradient);
CGColorSpaceRelease(rgbColorSpace);
}
I am sure there is something I am missing here. I have tried changing the RGB values to 0.0 instead of 1.0, changing the color space to gray scale, etc.
Any help pointing me in the right direction would be much appreciated. Thanks
I resolved the issue by making sure the view's background color was set to clear, then applying the view's layer as a mask on the image view.
I use CAGradient:
UIView * viewToGradient = // view to add gradient
UIColor * color1 = [UIColor lightGrayColor]; // gradient color 1
UIColor * color2 = [UIColor clearColor]; // gradient color 2
CAGradientLayer * gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = viewToGradient.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:(id)color1.CGColor, (id)color2.CGColor, nil];
gradientLayer.opacity = .6;
[viewToGradient.layer addSublayer:gradientLayer];

set line width to radial gradient

I am using radial gradient to draw circle. It is working fine but now I want to set border color and border width to that. I tried it but it was not working.
Here is my code,
CGGradientRef gradient;
CGColorSpaceRef colorSpace;
CGFloat locations[] = {0.0,1.0};
CGFloat components[] = { red2,green2,blue2,1.0,red1,green1,blue1,1.0 };
colorSpace = CGColorSpaceCreateDeviceRGB();
gradient = CGGradientCreateWithColorComponents(colorSpace,components,locations,
sizeof(locations)/sizeof(CGFloat));
CGPoint start = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2 ), end = CGPointMake(self.bounds.size.width/2 , self.bounds.size.height/2);
CGFloat startRadius = 0.0, endRadius = radius;
CGContextDrawRadialGradient(contextRef,gradient,start,startRadius,end,endRadius,0);
CGContextSetLineWidth(contextRef, 5.0);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
How can I set border color and width to it?
First add QuartzCore Framework and then try this code...
[[Firstbtn layer]setBorderColor:[[UIColor blackColor]CGColor]];
[[self.Firstbtn layer]setBorderWidth:2.3];
[[self.Firstbtn layer]setCornerRadius:15];

Fast way to redraw gradient?

I need to draw (a bit) complex gradients programmatically. Here is my params.
#define SHADOW_OPACITY 0.35
const size_t num_locations = 4;
const CGFloat locations[num_locations] = { 0, 0.12, 0.42, 1.0 };
const CGFloat components[num_locations * 2] = { 0.0, 1.0 * SHADOW_OPACITY,
0.0, 1.0 * SHADOW_OPACITY,
0.0, 0.73 * SHADOW_OPACITY,
0.0, 0.0 };
Three rings with opacity and a dashed ring inside. All works just fine.
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
[self drawGradientInContext:context];
CGContextSetLineWidth(context, CIRCLE_STROKE_WIDTH);
CGContextBeginPath(context);
CGFloat dashLength = DASH_LENGTH(self.circleRadius);
CGFloat dashArray[] = { dashLength, dashLength };
CGContextSetLineDash(context, 0, dashArray, 2);
CGContextAddArc(context, CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds), self.circleRadius, 0, 2 * M_PI, YES);
CGContextClosePath(context);
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextDrawPath(context, kCGPathStroke);
}
- (void)drawGradientInContext:(CGContextRef)context
{
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);
CGPoint gradientCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
CGContextDrawRadialGradient(context,
gradient,
gradientCenter,
self.circleRadius - 1,
gradientCenter,
self.circleRadius + SHADOW_WIDTH,
kCGGradientDrawsAfterEndLocation);
CGColorSpaceRelease(colorspace);
CGGradientRelease(gradient);
}
Well, I need to apply zoom.
- (void)zoom:(UIPinchGestureRecognizer *)sender
{
effectiveScale = beginGestureScale * sender.scale;
self.circleRadius = effectiveScale * BASE_RADIUS;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
beginGestureScale = effectiveScale ? effectiveScale : 1.0;
}
return YES;
}
Well, since that things are screwed up: it glitches as the hell!
What could I do there?

Resources