draw gradient orientation - iphone

So I have the following code:
-
(void) drawLinearGradient:(CGRect) rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 0.3, 1.0 };
CGColorRef grayColor = [UIColor colorWithRed:37/255.f green:37/255.f
blue:37/255.f alpha:1.0].CGColor;
CGColorRef blueColor = [UIColor colorWithRed:23.0/255.0 green:171.0/255.0
blue:219.0/255.0 alpha:1.0].CGColor;
NSArray *colors = [NSArray arrayWithObjects: (id) grayColor, (id) grayColor, (id) blueColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,
(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);
}
What this does is draw the gradient from top to bottom, how can I make it so it draws it from left to right?

Change these two lines:
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
to:
CGPoint startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMidY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMidY(rect));

Related

Draw the highlight blue color using UIImage or Code

From http://replyz.com/c/1244746-does-anyone-know-the-exact-cgcolorref-used-to-create-the-selection-highlight-when-using-uitableviewcellselectionstyleblue#
I saw someone did it with Code and he said the highlighted color is from a UIImage.
Where can I find the image?
(I want to highlight a UIButton with the UITableViewCellSelectionStyleBlue color)
I found the link http://replyz.com/c/1244746-does-anyone-know-the-exact-cgcolorref-used-to-create-the-selection-highlight-when-using-uitableviewcellselectionstyleblue# including some code which can be used to create the highlight. And I create a new UIImage with the Code.
Here is the code:
+ (UIImage *) imageForSelectedBlue {
CGRect rect = CGRectMake(0, 0, 10, 10);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 0.021, 0.548, 0.962, 1.000, 0.008, 0.364, 0.900, 1.000 };
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef selectionGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, selectionGradient, startPoint, endPoint, 0);
CGGradientRelease(selectionGradient);
CGColorSpaceRelease(rgbColorspace);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Actually, you can set the background image of the button. It is more efficient.
[button setBackgroundImage:buttonBackgroundPressed forState:UIControlStateHighlighted];

iOS - How to draw a transparent triangle in view

I am trying to do a custom tab bar with a transparent triangle that points into the tab bar's view.
Right now I am drawing a linear gradient and a gloss in the drawRect method for the background of this tab bar. I just need to add the transparent triangle on there. I know how to draw a triangle. I just need to know how to make it transparent to show the background beneath the tab bar view.
Anyone know how to do this?
Update
Here is the current code:
void drawGlossAndGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef endColor)
{
drawLinearGradient(context, rect, startColor, endColor);
CGColorRef glossColor1 = [UIColor colorWithRed:1.0 green:1.0
blue:1.0 alpha:0.35].CGColor;
CGColorRef glossColor2 = [UIColor colorWithRed:1.0 green:1.0
blue:1.0 alpha:0.1].CGColor;
CGRect topHalf = CGRectMake(rect.origin.x, rect.origin.y,
rect.size.width, rect.size.height/2);
drawLinearGradient(context, topHalf, glossColor1, glossColor2);
}
void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, 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);
}
- (void)drawTriangle
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGPoint pt1 = CGPointMake(0.0f, 0.0f);
CGPoint pt2 = CGPointMake(10.0f, 10.0f);
CGPoint pt3 = CGPointMake(20.0f, 0.0f);
CGPoint vertices[] = {pt1, pt2, pt3, pt1};
CGContextBeginPath(context);
CGContextAddLines(context, vertices, 3);
CGContextClosePath(context);
CGContextClip(context);
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorRef lightColor = [UIColor colorWithRed:65.0f/255.0f green:64.0f/255.0f
blue:66.0f/255.0f alpha:1.0].CGColor;
CGColorRef darkColor = [UIColor colorWithRed:37.0/255.0 green:31.0/255.0
blue:32.0/255.0 alpha:1.0].CGColor;
[self drawTriangle];
CGRect viewRect = self.bounds;
drawGlossAndGradient(context, viewRect, lightColor, darkColor);
}
I added the clip suggested below but that just made my background with the gradient and the gloss dissappear and the triangle become gray. Does anyone know what I am doing wrong here?
If you draw this gradient in drawRect: method just add clipping path before it.
Example:
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGPoint vertices[] = {coordinates of vertices};
CGContextBeginPath(ctx);
CGContextAddLines(ctx, vertices, sizeof(vertices)/sizeof(CGPoint));
CGContextClosePath(ctx);
CGContextClip(ctx);
// draw the gradient
}
Vertices - is an array with 7 points. 1 point per each corner of self.bounds and 3 points which are define the triangle.
For example:
(0) (1) (3) (4)
_____ ________________
| \ / |
| V |
| (2) |
(6) |_______________________|(5)
CGPoint vertices[7] = {CGPointZero, // origin
p1, p2, p3, // vertices of the triangle
{self.bounds.size.width, 0},
{self.bounds.size.width, self.bounds.size.height},
{0, self.bounds.size.height}
}
If anybody needs, this is a code to draw a colored triangle in a UITableView without using UIImageView. This method is good because, the size of triangle can vary and it is drawn programmatically. Also, you can probably change colors and make triangle transparent.
#implementation RRTriangleView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0.0, 0.0);
CGPathAddLineToPoint(path, NULL, - self.bounds.size.height / 2.0, self.bounds.size.height / 2.0);
CGPathAddLineToPoint(path, NULL, 0.0, self.bounds.size.height);
CGPathAddLineToPoint(path, NULL, 0.0f, 0.0f);
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
[shapeLayer setPath:path];
[shapeLayer setFillColor:[COLOR_CUSTOM_LIGHT_BLUE CGColor]];
[shapeLayer setStrokeColor:[COLOR_CUSTOM_LIGHT_BLUE CGColor]];
[shapeLayer setPosition:CGPointMake(self.bounds.size.width, 0.0f)];
[[self layer] addSublayer:shapeLayer];
CGPathRelease(path);
}
return self;
}
Init this TriangleView and add it to your cell, when it is selected :
- (RRTriangleView *)triangleView
{
if (! _triangleView) {
_triangleView = [[RRTriangleView alloc] initWithFrame:self.bounds];
_triangleView.layer.backgroundColor = [[UIColor clearColor] CGColor];
_triangleView.clipsToBounds = NO;
}
return _triangleView;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
//[super setSelected:selected animated:animated];
if (selected) {
[self addSubview:self.triangleView];
}
else {
[self.triangleView removeFromSuperview];
}
}
The size of triangleView is like your cell's view, it is transparent and it is drawn above.
I beleive that
[view setBackgroundColor:[UIColor clearColor]];
[view setOpaque:NO];
will make your view transparent.

CGContextSetShadowWithColor not working

This code should be showing a shadow, but it isn't:
CGContextRef context = UIGraphicsGetCurrentContext();
//Border
CGMutablePathRef outerPath = createRoundedRectForRect(self.bounds, MENU_BUTTON_OUTER_RADIUS);
CGContextSetFillColorWithColor(context, [[UIColor colorWithWhite:0 alpha:0.18] CGColor]);
CGContextAddPath(context, outerPath);
CGContextFillPath(context);
//Button
UIColor *buttonColor;
if (self.type == JMenuButtonTypeBlack) {
buttonColor = [UIColor colorWithWhite:0 alpha:1.0];
}
else if (self.type == JMenuButtonTypeWhite) {
buttonColor = [UIColor colorWithWhite:0.72 alpha:1.0];
}
CGRect insideRect = rectForRectWithInset(self.bounds, 3);
CGMutablePathRef innerPath = createRoundedRectForRect(insideRect, MENU_BUTTON_INNER_RADIUS);
CGPoint gradientTop = CGPointMake(0, insideRect.origin.y);
CGPoint gradientBottom = CGPointMake(0, insideRect.origin.y + insideRect.size.height);
//Base color
CGContextSaveGState(context);
CGContextSetFillColorWithColor(context, [buttonColor CGColor]);
CGContextAddPath(context, innerPath);
CGContextFillPath(context);
CGContextRestoreGState(context);
//Gradient 1
CGContextSaveGState(context);
CGFloat colors [] = {
1.0, 1.0, 1.0, 0.16,
0.0, 0.0, 0.0, 0.11
};
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2);
CGContextAddPath(context, innerPath);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, gradientTop, gradientBottom, 0);
CGGradientRelease(gradient), gradient = NULL;
CGColorSpaceRelease(baseSpace), baseSpace = NULL;
CGContextRestoreGState(context);
//Shadow
CGContextSaveGState(context);
CGContextAddPath(context, innerPath);
CGContextSetShadowWithColor(context, CGSizeMake(0, 2), 3.0, [[UIColor blackColor] CGColor]);
CGContextRestoreGState(context);
This is what it looks like so far. The shadow code doesn't make a difference:
You're not drawing anything after you set the shadow. You need to either stroke or fill (CGContextStrokePath() or CGContextFillPath()) the path in order for it to be drawn into the context and thus appear on screen.

How to fill a path with gradient in drawRect:?

filling a path with a solid color is easy enough:
CGPoint aPoint;
for (id pointValue in points)
{
aPoint = [pointValue CGPointValue];
CGContextAddLineToPoint(context, aPoint.x, aPoint.y);
}
[[UIColor redColor] setFill];
[[UIColor blackColor] setStroke];
CGContextDrawPath(context, kCGPathFillStroke);
I'd like to draw a gradient instead of solid red, but I am having trouble.
I've tried the code listed in the Question/Answer: Gradients on UIView and UILabels On iPhone
which is:
CAGradientLayer *gradient = [CAGradientLayer layer];
[gradient setFrame:rect];
[gradient setColors:[NSArray arrayWithObjects:(id)[[UIColor blueColor] CGColor],
(id)[[UIColor whiteColor] CGColor], nil]];
[[self layer] setMasksToBounds:YES];
[[self layer] insertSublayer:gradient atIndex:0];
However, this paints the entire view that this is in with the gradient, covering up my original path.
I would clip to the path you want to fill, and use CGContextDrawLinearGradient. Here is a simple implementation of drawRect: as an example:
- (void) drawRect:(CGRect)rect
{
// Create a gradient from white to red
CGFloat colors [] = {
1.0, 1.0, 1.0, 1.0,
1.0, 0.0, 0.0, 1.0
};
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2);
CGColorSpaceRelease(baseSpace), baseSpace = NULL;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextAddEllipseInRect(context, rect);
CGContextClip(context);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient), gradient = NULL;
CGContextRestoreGState(context);
CGContextAddEllipseInRect(context, rect);
CGContextDrawPath(context, kCGPathStroke);
}

Rounded rect with Gradient color

I have not really done much programming with Core Graphics. And I tend to stick with QuartzCore now that it does a lot of what I need through the layer property :)
However, I have a UIView, which is currently gradient. I'd like to add rounded corners to this UIView and the layer property does not do this when I draw the gradient:
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.95, // Start color
1.0, 1.0, 1.0, 0.60 }; // End color
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGRect currentBounds = self.bounds;
CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMaxY(currentBounds));
CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, midCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
I am not really sure where I should be rounding in the drawRect method. Thanks.
Have you checked previous question postings? I read one a while back about masking UIViews. I think the same applies pretty much on all objects which use drawRect
How to mask a square image into an image with round corners in the iPhone SDK?
Here's what I did, and it works fine as far as I can tell.
First, I borrowed Mr NilObject's code snippet from the above mentioned post.
I modified it to fit in an object (as he wrote it as a C function instead of a method)
I subclass UIView to create my own custom view. I overload initWithRect: to make my background transparent.
So basically:
set transparent background (in init), or clipping will be uggly
in drawRect, first clip, then draw inside the clipped area
The following is a working example:
//
// TeleView.m
//
#import "TeleView.h"
#implementation TeleView
/**** in init methods, set background to transparent,
otherwise, clipping shows a black background ****/
- (id) initWithFrame:(CGRect)frame {
if((self = [super initWithFrame:frame])) {
[self setBackgroundColor:[UIColor colorWithWhite:0.0f alpha:0.0f]];
}
return self;
}
- (void) clipCornersToOvalWidth:(float)ovalWidth height:(float)ovalHeight
{
float fw, fh;
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = CGRectMake(0.0f, 0.0f, self.frame.size.width, self.frame.size.height);
if (ovalWidth == 0 || ovalHeight == 0) {
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);
fw = CGRectGetWidth (rect) / ovalWidth;
fh = CGRectGetHeight (rect) / ovalHeight;
CGContextMoveToPoint(context, fw, fh/2);
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
CGContextClosePath(context);
CGContextRestoreGState(context);
}
-(void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/**** here is what I modified. ****/
[self clipCornersToOvalWidth:20.0f height:20.0f];
CGContextClip(currentContext);
/**** below this is your own code ****/
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 0.0, 0.0, 0.60, // Start color
0.0, 1.0, 0.0, 0.40 }; // End color
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGRect currentBounds = self.bounds;
CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMaxY(currentBounds));
CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, midCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
#end
NSArray *colors = [NSArray arrayWithObjects:fromColor.CGColor,toColor.CGColor, nil];
NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
NSNumber *stopTwo = [NSNumber numberWithFloat:1.0];
NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, nil];
CAGradientLayer *headerLayer = [CAGradientLayer layer];
headerLayer.colors = colors;
headerLayer.locations = locations;
headerLayer.borderColor = borderColor.CGColor; // border line color**strong text**
headerLayer.borderWidth = width;// For Thickness of border line
headerLayer.cornerRadius = radius;//For Rounded Corner if You want to make rounded Corner
headerLayer.frame = frame;
[view.layer insertSublayer:headerLayer atIndex:0];
Also make sure to import "QuartzCore" framework