Draw top and bottom lines on a UIView - ios

I am trying to draw lines on the top and bottom edge of a UIView. But the line does not get drawn all the way to the right edge of the view controller.
Following is the code I am using to draw the lines:
- (void)addBorders
{
CALayer *upperBorder = [CALayer layer];
CALayer *bottomBorder = [CALayer layer];
upperBorder.backgroundColor = [[UIColor colorWithRed:225/255.0 green:220/255.0 blue:214/255.0 alpha:1.0f] CGColor];
upperBorder.frame = CGRectMake(0, 0, CGRectGetWidth(self.recentTuneinView.frame), 0.5f);
bottomBorder.backgroundColor = [[UIColor colorWithRed:154/255.0 green:154/255.0 blue:154/255.0 alpha:1.0f] CGColor];
bottomBorder.frame = CGRectMake(0, 58.0f, CGRectGetWidth(self.recentTuneinView.frame), 0.5f);
[self.recentTuneinView.layer addSublayer:upperBorder];
[self.recentTuneinView.layer addSublayer:bottomBorder];
}
Here is an image showing the problem:
What am I missing in the code?
Thanks.

Adding sub layers is not a scalable solution like it creates problems when rotating the device or view size change.
My advise is to create a custom view and implement drawRect: something like this:
- (void)drawRect:(CGRect)iRect {
CGContextRef aContext = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(aContext, 0.5);
// Set Top Line Color
CGContextSetStrokeColorWithColor(aContext, [[UIColor colorWithRed:225/255.0 green:220/255.0 blue:214/255.0 alpha:1.0f] CGColor]);
// Top Line
CGContextMoveToPoint(aContext, 0, 0);
CGContextAddLineToPoint(aContext, iRect.size.width, 0);
// Set Bottom Line Color
CGContextSetStrokeColorWithColor(aContext, [[UIColor colorWithRed:225/255.0 green:220/255.0 blue:214/255.0 alpha:1.0f] CGColor]);
// Bottom Line
CGContextMoveToPoint(aContext, 0, 58.0);
CGContextAddLineToPoint(aContext, iRect.size.width, 58.0);
}

Here is the solution. Above code updated.
- (void)addBorders
{
CALayer *upperBorder = [CALayer layer];
CALayer *bottomBorder = [CALayer layer];
upperBorder.backgroundColor = [[UIColor colorWithRed:225/255.0 green:220/255.0 blue:214/255.0 alpha:1.0f] CGColor];
upperBorder.frame = CGRectMake(0, 0, CGRectGetWidth(self.recentTuneinView.frame) + 60, 0.5f);
bottomBorder.backgroundColor = [[UIColor colorWithRed:154/255.0 green:154/255.0 blue:154/255.0 alpha:1.0f] CGColor];
bottomBorder.frame = CGRectMake(0, 58.0f, CGRectGetWidth(self.recentTuneinView.frame) + 60, 0.5f);
[self.recentTuneinView.layer addSublayer:upperBorder];
[self.recentTuneinView.layer addSublayer:bottomBorder];
}

Update your code.
CALayer *upperBorder = [CALayer layer];
CALayer *rightBorder = [CALayer layer];
CALayer *bottomBorder = [CALayer layer];
upperBorder.backgroundColor = [[UIColor colorWithRed:225/255.0 green:220/255.0 blue:214/255.0 alpha:1.0f] CGColor];
rightBorder.backgroundColor = upperBorder.backgroundColor;
upperBorder.frame = CGRectMake(0, 0, CGRectGetWidth(recentTuneinView.frame), 0.5f);
rightBorder.frame = CGRectMake(CGRectGetWidth(recentTuneinView.frame)-0.5, 0, 0.5f,CGRectGetHeight(recentTuneinView.frame));
bottomBorder.backgroundColor = [[UIColor colorWithRed:154/255.0 green:154/255.0 blue:154/255.0 alpha:1.0f] CGColor];
bottomBorder.frame = CGRectMake(0, 58.0f, CGRectGetWidth(recentTuneinView.frame), 0.5f);
[recentTuneinView.layer addSublayer:upperBorder];
[recentTuneinView.layer addSublayer:rightBorder];
[recentTuneinView.layer addSublayer:bottomBorder];
Note: You have to add right sublayer frame also.

Related

Set circle in centre of my UIView

I have one UIView with size 141 X 161. Then I created a circle .Here is that code:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 86, 79)] CGPath]];
[[self.photoView layer] addSublayer:circleLayer];
[circleLayer setStrokeColor:[[UIColor blackColor] CGColor]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
}
photoview is my uiview
When I run it's not in centre,
I need my circle in perfect centre of inside my UIView ( 141 x 161). And also need to set outside border.
And my circle is think.how to set radius at 1.
And my circle fill should be #222222
Border: thickness = 1.9
color = white
position = centre
I am new to iOS.
Try this :
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(27, 41, 86, 79)] CGPath]];
[[self.photoView layer] addSublayer:circleLayer];
[circleLayer setStrokeColor:[[UIColor whiteColor] CGColor]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
circleLayer.lineWidth = 0.5;
circleLayer.shadowColor = [UIColor whiteColor].CGColor;
circleLayer.shadowOpacity = 0.4;
circleLayer.borderColor = [UIColor whiteColor] .CGColor;
circleLayer.borderWidth = 2;
circleLayer.fillColor =[UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.25].CGColor;
circleLayer.borderColor = [[UIColor whiteColor] CGColor];

How to connect buttons frame?

I have three buttons, all have different direction.
I have to connect them with a red line.
Just like Tic Tec Toc if game over than how to connect them with line:
How do I set line between them??
Or you can use this code..
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lineView];
This is one way of drawing line :
Here you need to subclass UIView and then use CoreGraphics calls in the drawRect method:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 4.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 25, 25);
CGContextAddLineToPoint(context, 75, 75);
CGContextStrokePath(context);
}
Another way is using UIBezierPath as follows :
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
[self.view.layer addSublayer:shapeLayer];

How to draw the gradient in iOS

I want to draw the Circular progress view with gradient as image :
Design Image
I tried the below code but the result color is not correct. This is my code:
//draw gradient
CGFloat colors [] = {
1.0, 0.7,
0.2, 0.4
};
CGFloat locations[] = { 0.0, 1.0 };
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceGray(); // gray colors want gray color space
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, locations, 2);
CGColorSpaceRelease(baseSpace), baseSpace = NULL;
CGContextSaveGState(context);
CGContextAddPath(context, progressPath);
CGContextClip(context);
CGRect boundingBox = CGPathGetBoundingBox(progressPath);
CGPoint gradientStart = CGPointMake(0.0, CGRectGetMinY(boundingBox));
CGPoint gradientEnd = CGPointMake(1.0, CGRectGetMaxY(boundingBox));
CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, 0);
CGGradientRelease(gradient), gradient = NULL;
CGContextRestoreGState(context);
The progressPath is the progress line with color :
[UIColor colorWithRed:21/255.0f green:182/255.0f blue:217/255.0f alpha:1.0]
UPDATE:
This is an image my code produced: Result Image
The result image is not the same the design, the color is not the same. I dont know why.
Please help me to correct this. Thanks in advance.
The kind of gradient you are looking for, where the color varies as a function of the angle around a center point, is called an angle gradient. Unfortunately, iOS does not have a built-in way to draw angle gradients, but you can do it using an open-source library such as paiv/AngleGradientLayer.
Working code:
- (void) setGradientWithFrame:(CGRect)frame
{
//create the gradient
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = frame;
//this example is white-black gradient, change it to the color you want..
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor], (id)[[UIColor blackColor] CGColor], nil];
gradient.cornerRadius = frame.size.height/2.0f;
[self.view.layer insertSublayer:gradient atIndex:0];
CALayer *whiteCircle = [CALayer layer];
whiteCircle.frame = CGRectMake(frame.origin.x + 10, frame.origin.y + 10, frame.size.width - 20, frame.size.height - 20);
whiteCircle.backgroundColor = [[UIColor whiteColor] CGColor];
whiteCircle.cornerRadius = whiteCircle.frame.size.width/2.0f;
[self.view.layer insertSublayer:whiteCircle atIndex:1];
CALayer *whitesquare = [CALayer layer];
whitesquare.frame = CGRectMake(50, frame.size.height - 20, 25, 25);
whitesquare.backgroundColor = [[UIColor whiteColor] CGColor];
whitesquare.transform = CATransform3DMakeRotation(-20.0 / 180.0 * M_PI, 0.0, 0.0, 1.0);
[self.view.layer insertSublayer:whitesquare atIndex:2];
}
to call the method:
[self setGradientWithFrame:CGRectMake(0, 0, 100, 100)];
PS. change the color to the color of gradient to the color you want:

Adding inner shadow on uitextfield and uitextview

I am trying to add inner shadow on few UITextField and UITextView. I have set cornerRadius property for these controls to 1.0. and I am using the code which is mentioned below to create the inner shadow. But problem is that the shadow appears with the steep rectangular corners while the text view and the text field are with rounded corners.
I am calling following method in my viewcontroller class to add the shadow on my text field.
[self addInnerShadow:myTextField.frame];
- (void)addInnerShadow:(CGRect)frame
{
CAShapeLayer* shadowLayer = [CAShapeLayer layer];
[shadowLayer setFrame:frame];
[shadowLayer setShadowColor:[[UIColor blackColor] CGColor]];
[shadowLayer setShadowOffset:CGSizeMake(0.0f, 0.0f)];
[shadowLayer setShadowOpacity:1.0f];
[shadowLayer setShadowRadius:5];
[shadowLayer setFillRule:kCAFillRuleEvenOdd];
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectInset(CGRectMake(0, 0, frame.size.width, frame.size.height),-5, -5));
CGMutablePathRef someInnerPath = CGPathCreateMutable();
CGPathAddRect(someInnerPath, NULL, CGRectInset(CGRectMake(0, 0, frame.size.width, frame.size.height), 0, 0));
CGPathAddPath(path, NULL, someInnerPath);
CGPathCloseSubpath(path);
[shadowLayer setPath:path];
CGPathRelease(path);
CAShapeLayer* maskLayer = [CAShapeLayer layer];
[maskLayer setPath:someInnerPath];
[shadowLayer setMask:maskLayer];
[[self.view layer] addSublayer:shadowLayer];
}
This
CGContextRef context = UIGraphicsGetCurrentContext();
// Shadow
UIColor* shadow4 = [[UIColor blackColor] colorWithAlphaComponent: 0.81];
CGSize shadow4Offset = CGSizeMake(0.1, 2.1);
CGFloat shadow4BlurRadius = 5;
UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRoundedRect: CGRectMake(20.5, 26.5, 200, 40) cornerRadius: 4];
[[UIColor whiteColor] setFill];
[rectanglePath fill];
CGRect rectangleBorderRect = CGRectInset([rectanglePath bounds], -shadow4BlurRadius, - shadow4BlurRadius);
rectangleBorderRect = CGRectOffset(rectangleBorderRect, -shadow4Offset.width, - shadow4Offset.height);
rectangleBorderRect = CGRectInset(CGRectUnion(rectangleBorderRect, [rectanglePath bounds]), -1, -1);
UIBezierPath* rectangleNegativePath = [UIBezierPath bezierPathWithRect: rectangleBorderRect];
[rectangleNegativePath appendPath: rectanglePath];
rectangleNegativePath.usesEvenOddFillRule = YES;
CGContextSaveGState(context);
{
CGFloat xOffset = shadow4Offset.width + round(rectangleBorderRect.size.width);
CGFloat yOffset = shadow4Offset.height;
CGContextSetShadowWithColor(context,
CGSizeMake(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset)),
shadow4BlurRadius,
shadow4.CGColor);
[rectanglePath addClip];
CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(rectangleBorderRect.size.width), 0);
[rectangleNegativePath applyTransform: transform];
[[UIColor grayColor] setFill];
[rectangleNegativePath fill];
}
CGContextRestoreGState(context);
[[UIColor blackColor] setStroke];
rectanglePath.lineWidth = 0.5;
[rectanglePath stroke];
Will produce this. You can manipulate this to get your desired effect.
Create path with UIBezierPath
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:CGSizeMake(5.0, 5.0)];
And than use it with Layer.

CAGradientLayer with CAShapeLayer mask not showing

I have the following code:
- (void)setupLayer {
self.faucetShape = [CAShapeLayer layer];
self.faucetShape.strokeColor = [[UIColor blackColor] CGColor];
self.faucetShape.lineWidth = 2;
self.faucetShape.fillColor = nil;
self.faucetShape.path = [self faucetPath].CGPath; // faucetPath returns a 4 point diamond shaped UIBezierPath*
self.faucet = [CAGradientLayer layer];
self.faucet.mask = self.faucetShape;
self.faucet.colors = #[(id)[UIColor redColor].CGColor, (id)[UIColor redColor].CGColor];
[self.layer addSublayer: self.faucet];
}
But it shows nothing. Not sure what I'm missing (other than my graphic).
(faucet and faucetPath are both properties)
UPDATE
OK, I guess a CAGradientLayer has to have a meaningful frame. I assume a CAShapeLayer's frame isn't as meaningful, since the path can go outside the frame. Adding the following line made it show up:
self.faucet.frame = CGRectMake(0, 0, 64, 64);
So NOW my question is, is there a way to avoid having to do that? I'd just like the frame of the layer to implicitly be that of the containing View/Layer.
You need to set the frame of the layers. The following code will draw a red circle:
- (void)setupLayer
{
CAShapeLayer *faucetShape = [CAShapeLayer layer];
faucetShape.frame = CGRectMake(0, 0, 100, 100);
faucetShape.strokeColor = [[UIColor blackColor] CGColor];
faucetShape.lineWidth = 2;
faucetShape.fillColor = nil;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, nil, CGRectMake(0, 0, 100, 100));
faucetShape.path = path;
CGPathRelease(path);
CAGradientLayer *faucet = [CAGradientLayer layer];
faucet.frame = CGRectMake(10, 10, 100, 100);
faucet.mask = faucetShape;
faucet.colors = #[(id)[UIColor redColor].CGColor, (id)[UIColor redColor].CGColor];
[self.view.layer addSublayer: faucet];
}

Resources