I have a view in storyboard controller which extends my custom UIView and when I try to draw a gradient in drawRect it displays fine when loading on to device/sim via XCode but when I install via TestFlight after uploading to ITunes Connect the gradient isn't present at first (displays black background) - it needs a rotation of the device and the gradient displays fine again. What could be causing this behaviour?
- (void)drawRect:(CGRect)rect {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
NSArray *gradientColors = [NSArray arrayWithObjects:
(id)[[self colorWithHexString:#"FF7542"]CGColor],
(id)[[self colorWithHexString:#"FF7542"]CGColor],
(id)[[self colorWithHexString:#"FFC0A1"]CGColor],
nil];
CGFloat gradientLocations[] = {0, 1};
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) gradientColors, gradientLocations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
NSShadow *shadow = [[NSShadow alloc] init];
[shadow setShadowColor : BLACK_SHADOW];
[shadow setShadowOffset : CGSizeMake (1.0, 1.0)];
}
I solved this by creating my gradient another way and strangely it shows first time when loaded without the need for a rotation.
CGContextRef current_context = UIGraphicsGetCurrentContext();
CGContextSaveGState(current_context);
// Gradient
CGFloat locations[2] = {0.0, 1.0};
CGFloat components[8] = {1.00,0.75,0.63,1.0,1.00,0.46,0.26,1.0};
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, 2);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(current_context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorspace);
Related
Hi I have draw a gradient in core graphic using drawRect function..
but I don't know how to draw a border to surround this view?
this is my code, could anyone help?
- (void)drawRect:(CGRect)rect {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
NSArray *gradientColors = [NSArray arrayWithObjects:(id)[UIColor blackColor].CGColor, [UIColor colorWithRed:90/255.0 green:0 blue:0 alpha:1].CGColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) gradientColors, NULL);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
If you just want to draw a border around the view, try this:
UIBezierPath *border = [UIBezierPath bezierPathWithRect:rect];
[[UIColor redColor] setStroke];
[border setLineWidth:4.0];
[border stroke];
Use it at the end of drawRect: method.
I write some code for creating the below with UIBezierPath but it didn't work. Can someone help me what's wrong with my code.
but i was tried with drawRect: it works fine....My problem is same i need in UIBezierPath as,
+ (UIBezierPath *)DropShape:(CGRect)Frame {}
my code using drawRect: is
CGContextRef context = UIGraphicsGetCurrentContext();
CGGradientRef gradient;
CGColorSpaceRef colorspace;
CGFloat locations[3] = { 0.0, 0.5, 1.0 };
NSArray *colors = #[(id)[UIColor redColor].CGColor];
colorspace = CGColorSpaceCreateDeviceRGB();
gradient = CGGradientCreateWithColors(colorspace,
(CFArrayRef)colors, locations);
CGPoint startPoint, endPoint;
CGFloat startRadius, endRadius;
startPoint.x = self.frame.size.width/2;
startPoint.y = 30;
endPoint.x = 175;
endPoint.y = 175;
startRadius = 0;
endRadius = 75;
CGContextDrawRadialGradient(context, gradient, startPoint,
startRadius, endPoint, endRadius, 0);
Thanks in advance...
There is an app called PaintCode which you can try for free.
You can draw onto a canvas and it will produce the drawRect code that you can copy and paste into your app.
I don't think you can copy from the trial version but it will create the path which you can type into your code manually.
It's worth a look.
I have a simple drawing routine that allows the user to draw two enclosed ovals on the screen. I want to fill the ovals with a gradient, using the inner oval to represent the "percentage" of the gradient. i.e. Th gradient will smoothly transition between the outside oval to the inside oval.
I have the interactive drawing working fine, now I just need to fill with the gradient.
Any thoughts? The docs only talk about perfectly circular gradients, not ovals.
_mike
I do not know whether it is possible oval gradient . But you can transform circle to oval. The idea is to draw a circle in transformed coordinate system.
Sample of code:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextScaleCTM(context, 1.0, 0.5);
CGGradientRef gradient;
CGColorSpaceRef colorspace;
CGFloat locations[2] = { 0.0, 1.0};
NSArray *colors = #[(id)[UIColor whiteColor].CGColor, (id)[UIColor blueColor].CGColor];
colorspace = CGColorSpaceCreateDeviceRGB();
gradient = CGGradientCreateWithColors(colorspace, (CFArrayRef)colors, locations);
CGPoint startPoint, endPoint;
CGFloat startRadius, endRadius;
startPoint.x = 180;
startPoint.y = 180;
endPoint.x = 180;
endPoint.y = 180;
startRadius = 0;
endRadius = 100;
CGContextDrawRadialGradient (context, gradient, startPoint, startRadius, endPoint, endRadius, 0);
CGContextRestoreGState(context);
}
Result of running code:
My goal is
1. add gradient for my view (done)
2. add drop shadow for the bottom edge of my view ( issue at here )
What I am doing is :
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *whiteColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
UIColor *lightGrayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0];
CGRect paperRect = self.bounds;
// Fill with gradient
[self drawLinearGradient:context for:paperRect start:whiteColor.CGColor end:lightGrayColor.CGColor];
CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextSetLineWidth(context, .9);
CGContextStrokeRect(context, paperRect);
// Add shadow
CGContextSetShadowWithColor(context, CGSizeMake(0, self.frame.size.height), 9.0, [UIColor blueColor].CGColor);
}
-(void)drawLinearGradient:(CGContextRef)context for:(CGRect)rect start:(CGColorRef)startColor end:(CGColorRef)endColor {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 1.0 };
NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
However, what I am getting is the picture below without shadow at all
Am I on the right track but missing something in the middle ? Please help if you have any ideas..
You need to set the shadow properties before drawing whatever it is that's supposed to have the shadow. Put your call to CGContextSetShadowWithColor before the call to CGContextStrokeRect.
Also, the offset should probably not be as large as you're making it. The shadow offset controls how much the shadow is offset from the pixels that were drawn with that shadow, so unless you want the shadow to actually start very far away from your rect you probably want an offset of just a pixel or so, like CGSizeMake(0.0, 1.0).
i have just a problem with my MKPolyLineView. I simply try to make a color gradient to the Polyline, but with CAGradient it doenst work. I subclasses MKPolylineView and redrawing in
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
UIColor *darker = [UIColor blackColor];
CGFloat baseWidth = self.lineWidth / zoomScale;
// draw the dark colour thicker
CGContextAddPath(context, self.path);
CGContextSetStrokeColorWithColor(context, darker.CGColor);
CGContextSetLineWidth(context, baseWidth * 1.5);
CGContextSetLineCap(context, self.lineCap);
CGContextStrokePath(context);
// now draw the stroke color with the regular width
CGContextAddPath(context, self.path);
CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor);
CGContextSetLineWidth(context, baseWidth);
CGContextSetLineCap(context, self.lineCap);
CGContextStrokePath(context);
[super drawMapRect:mapRect zoomScale:zoomScale inContext:context];
}
but even that is not working (StrokeColor = red). Any ideas how to get a gradient into
the Polyline? (Highcolor, centercolor, lowcolor)
Thanks everyone.
To paint a MKPolyline with a gradient, you can use a custom subclass of MKPolylineView. As CoreGraphics does not support stroking a path with a gradient, we have to
convert the path to a shape that traces the paths edge using CGPathCreateCopyByStrokingPath
clip the context to that shape
fill using CGContextDrawLinearGradient
Here is a subclass to get you started:
#interface TWOGradientPolylineView : MKPolylineView
#end
#implementation TWOGradientPolylineView
- (void)strokePath:(CGPathRef)path inContext:(CGContextRef)context
{
CGFloat lineWidth = CGContextConvertSizeToUserSpace(context, (CGSize){self.lineWidth, self.lineWidth}).width;
CGPathRef pathToFill = CGPathCreateCopyByStrokingPath(path, NULL, lineWidth, self.lineCap, self.lineJoin, self.miterLimit);
CGRect rect = CGPathGetBoundingBox(pathToFill);
CGContextAddPath(context, pathToFill);
CGPathRelease(pathToFill);
CGContextClip(context);
CGFloat gradientLocations[2] = {0.0f, 1.0f};
CGFloat gradientColors[8] = {1.0f, 0.0f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 0.75f};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocations, 2);
CGColorSpaceRelease(colorSpace);
CGPoint gradientStart = rect.origin;
CGPoint gradientEnd = {CGRectGetMaxX(rect), CGRectGetMaxY(rect)};
CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient);
}
#end
Here is a screenshot of a path drawn with the class above: