How to fix invalid context 0x0 with UIBezierPath? - ios

I am trying to find the best way to implement an rounded rectangle (e.g. looling like the iphone icons). My search suggested using UIBezierPath.
In order to test that class I made a new xcode template (single view application) and basically just added the following lines in ViewController's viewDidLoad:
UIBezierPath* path = [UIBezierPath
bezierPathWithRoundedRect: CGRectMake(10, 10, 120, 120)
cornerRadius: 5];
[[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0] setFill];
[path stroke];
[path fill];
Now I get several "...invalid context 0x0 error...". I assume that I have to set a context first?! But how do I do this or if not fix those errors otherwise?
My search on that error came up with a few posts. Unfortunaltely all of them seemed to have rather complex coding associated. I'm pretty sure however that I have just a very basic misunderstanding here.
Thank you!

you can use this and assign that in layer of your view
UIBezierPath *maskpath=[UIBezierPath bezierPathWithRoundedRect:view1.bounds
byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight
cornerRadii:CGSizeMake(10.0,10.0)];
CAShapeLayer *maskLayer=[CAShapeLayer layer];
maskLayer.frame=view1.bounds;
maskLayer.path=maskpath.CGPath;
[view1.layer addSublayer:maskLayer];

in case it is helpful for someone else: on basis of the code provided by johnykumar and another post on a similar topic:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
CGRect frame = CGRectMake(50.0, 50.0, 150.0, 150.0);
CGFloat radius = 20.0;
UIView *frontView = [[UIView alloc] initWithFrame:frame];
frontView.backgroundColor = [UIColor redColor];
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect:frontView.bounds
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:CGSizeMake(radius, radius)].CGPath;
frontView.layer.mask = maskLayer;
[self.view addSubview:frontView];
}

Related

How to get CAShapeLayer's frame confront to its superview?

Can anybody help me to get frame of CAShapeLayer which is been added in UIImageView as a SubLayer?
Following is my code for the same:
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.15].CGColor;
shapeLayer.strokeColor = [UIColor redColor].CGColor;
shapeLayer.lineWidth = 3.0;
shapeLayer.zPosition = 1;
[_imgBackground.layer insertSublayer:shapeLayer atIndex:1];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 50)]; // left top point of rack
[path addLineToPoint:CGPointMake(100, 50)]; // right top point of rack
[path addLineToPoint:CGPointMake(100, 100)]; // right bottom point of rack
[path addLineToPoint:CGPointMake(50, 100)]; // left bottom point of rack
[path closePath]; // closing rectangle/path
shapeLayer.path = path.CGPath;
As I know we can get frame from the following line:
CGRect bounds = CGPathGetBoundingBox(shapeLayer.path);
But it only returns frame according to self.view
I want its frame according to UIImageView.
Thanks in advance.
Well I got the answer from James's comment. Following line saved my day:
CGRect bounds = [self.view convertRect:CGPathGetBoundingBox(shapeLayer.path) toView:_imgBackground];
from this reference.

How to make a transparent cut on UIVisualEffectView?

In my app , I made a see through UIView by subclassing simple UIView's. However, If I try to do the same using UIVisualEffectView, I am not able to do it.
Here is what I am able to do using normal UIView:
When I use the UIVisualEffectView in place of green UIView,I cannot see the see through UIView , even though see through UIView is added to the UIVisualEffectView as subview.
Code:
- (void)drawRect:(CGRect)rect { //this is same for the UIVIew and for the UIVisualEffectView
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
// Clear any existing drawing on this view
// Remove this if the hole never changes on redraws of the UIView
CGContextClearRect(context, self.bounds);
// Create a path around the entire view
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:self.bounds];
// Your transparent window. This is for reference, but set this either as a property of the class or some other way
CGRect transparentFrame;
// Add the transparent window
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:transparentFrame cornerRadius:5.0f];
[clipPath appendPath:path];
// NOTE: If you want to add more holes, simply create another UIBezierPath and call [clipPath appendPath:anotherPath];
// This sets the algorithm used to determine what gets filled and what doesn't
clipPath.usesEvenOddFillRule = YES;
// Add the clipping to the graphics context
[clipPath addClip];
// set your color
UIColor *tintColor = [UIColor greenColor];
// (optional) set transparency alpha
CGContextSetAlpha(context, 0.7f);
// tell the color to be a fill color
[tintColor setFill];
// fill the path
[clipPath fill];
}
Question: Why this didn't work with UIVisualEffectView ?
Add following global variables in your ViewController.h file-
CAShapeLayer *fillLayer;
UIVisualEffectView *overlayView;
Add following methods in your ViewController.m file-
-(void)addOverlay:(CGRect)rect{
float x = rect.origin.x;
float y = rect.origin.y;
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height) cornerRadius:0];
UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(x, y, rect.size.width, rect.size.height) cornerRadius:5];
[path appendPath:circlePath];
[path setUsesEvenOddFillRule:YES];
[self removeOverlay];
overlayView = [[UIVisualEffectView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height+64)];
overlayView.backgroundColor = [UIColor clearColor];
[self.view addSubview:overlayView];
fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor colorWithRed:78/255.0 green:103/255.0 blue:135/255.0 alpha:1.0].CGColor;
fillLayer.opacity = 0.85;
[[UIApplication sharedApplication].keyWindow.layer addSublayer:fillLayer];
}
-(void)removeOverlay{
[overlayView removeFromSuperview];
[fillLayer removeFromSuperlayer];
}
and call it as -
[self addOverlay:rect];

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];

rounded corner uilabel not visible (xcode 4.5.2)

I am new to IOS development, try to create top rounded corner label
by following link
How do I round only the top two corners of a UILabel?
But after applying the mask, the whole label cannot be seen, Any clue?
Here is my code.
#synthesize title;
- (void)viewDidLoad
{
[super viewDidLoad];
title.layer.borderColor=[[UIColor blueColor]CGColor];
title.layer.borderWidth=2;
UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:title.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(10.0f, 10.0f)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame=title.bounds;
maskLayer.path = maskPath.CGPath;
title.layer.mask = maskLayer;
}
EDITED
Tried the suggestion to create the label in program, the layout become
https://docs.google.com/file/d/0B60xg2ZCEjOqeTBEWG92N0NodFU/edit?usp=sharing
The corner disappear and I still want to set the mask the "title" labal?
EDITED
Finally give up, for others benefit,I wrap the label in uiview , map the uiview to a class (i.e. Myview.m), and put the same code in method "- (void)drawRect:(CGRect)rect{}" in "Myview.m". The display showed as what I want!.
I'm not sure if this is your problem because you didn't show how the title label is created, but if you're creating it in code, you need to be sure to alloc/init the label, as well as give it a frame and then add it as a subview of its superview.
title = [[UILabel alloc] initWithFrame:CGRectMake(100.0f, 100.0f, 60.0f, 30.0f)];
title.layer.borderColor=[[UIColor blueColor]CGColor];
title.layer.borderWidth=2;
UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:title.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(10.0f, 10.0f)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame=title.bounds;
maskLayer.path = maskPath.CGPath;
title.layer.mask = maskLayer;
[self.view addSubview:title];
first of all my advice is don't use "title" as a UILabel name because all UIViewController has a property that name is title.
After changing label name and sure IBOutlet is connected add this code:
lblTitle.layer.masksToBounds = YES;
I just figure out if you create a label on storyboard you dont need to alloc again. I wrote this code and it works;
_L_corner.layer.borderColor =[[UIColor blueColor] CGColor];
_L_corner.layer.borderWidth = 5.0f;
_L_corner.layer.cornerRadius = 3.0f;
Finally give up, for others benefit, and used another work around:-
1) wrap the label in uiview ,
2) map the uiview to a class (i.e. Myview.m),
3) put the same code in method
- (void)drawRect:(CGRect)rect{
title.layer.borderColor=[[UIColor blueColor]CGColor];
title.layer.borderWidth=2;
UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:title.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(10.0f, 10.0f)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame=title.bounds;
maskLayer.path = maskPath.CGPath;
title.layer.mask = maskLayer;
}
in "Myview.m".
The display showed as what I want!

How to remove sharp rectangle edges from UIButton control?

Take a look at the following image:
As you can see the edges are sharp rectangle and they are coming out of the rounded corner button. How can I not show the edges and only show the round button?
UPDATE (Solution):
I used the following code to achieve the round corners:
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.stopButton.bounds
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:CGSizeMake(12.0, 12.0)];
// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.stopButton.bounds;
maskLayer.path = maskPath.CGPath;
// Set the newly created shape layer as the mask for the image view's layer
self.stopButton.layer.mask = maskLayer;
NEW PROBLEM:
This code gives me the error on the startButtonRound.layer.cornerRadius line.
UIButton *roundStartButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
roundStartButton.frame = CGRectMake(10, 10, 100, 20);
[roundStartButton setBackgroundImage:[UIImage imageNamed:#"green_gradient.jpg"] forState:UIControlStateNormal];
roundStartButton.layer.cornerRadius = 12.0;
UIBarButtonItem *startButton = [[UIBarButtonItem alloc] initWithCustomView:roundStartButton];
You could do this with CALayer alone:
CALayer *myLayer = [CALayer layer];
[myLayer setMasksToBounds:YES];
[myLayer setCornerRadius:5.0f];
[myLayer setBorderWidth:1.0f];
[myLayer setBorderColor: [[UIColor blackColor] CGColor]];
[myLayer setBackgroundColor: [[UIColor whiteColor] CGColor]];
You'll also want to include the QuartzCore framework and include the frameworks header in your own.
#include <QuartzCore/QuartzCore.h>
Hope this helps
Tim
I think all that can be accomplished with:
self.stopButton.layer.cornerRadius = 12.0;
But did you try
self.stopButton.opaque = NO;
self.stopButton.backgroundColor = [UIColor clearColor];
?
form the look of the image you have set your UIButton bckground color to 'White'. Make it 'Clear Color'.

Resources