UIView rounded corners - objective-c

I have to round only upper corners of UIView. I'm trying to use the following code:
UIBezierPath *maskEmailPath = [UIBezierPath bezierPathWithRoundedRect:self.emailandAccessView.bounds byRoundingCorners:UIRectCornerBottomLeft cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskEmailLayer = [CAShapeLayer layer];
maskEmailLayer.frame = self.myview.bounds;
maskEmailLayer.path = maskEmailPath.CGPath;
self.myview.layer.mask = maskEmailLayer;
but it hides everything in that view. Can anyone please help me.

This is how you do it.
CALayer *capa = self.view.layer;
CGRect bounds = capa.bounds;
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight)
cornerRadii:CGSizeMake(5.0, 5.0)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = bounds;
maskLayer.path = maskPath.CGPath;
[capa addSublayer:maskLayer];
capa.mask = maskLayer;

Related

iOS 10 How to animate UIBezierPath of UIVisualEffectView maskView

I just updated to Xcode 8 and I had problem with Blur (UIVisualEffectView) on iOS 10, but I solve it. But after I fixed the blur layer mask second problem is appears, when I getting the reference of maskView from UIVisualEffectView and apply the new UIBezierPath nothing happens.
Code example:
-(void)prepareEffectView{
//Frame
CGRect frame = self.view.bounds;
UIView *maskView = [[UIView alloc] initWithFrame:frame];
maskView.backgroundColor = [UIColor blackColor];
maskView.layer.mask = ({ // This mask draws a rectangle and crops a circle inside it.
UIBezierPath *maskLayerPath = [UIBezierPath bezierPath];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:frame]];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(self.btnScan.center.x, self.btnScan.center.y, 0, 0)]];
[maskLayer setPath:maskLayerPath.CGPath];
[maskLayerPath setUsesEvenOddFillRule:YES];
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = maskLayerPath.CGPath;
mask.fillRule = kCAFillRuleEvenOdd;
mask;
});
self.visualEffectView.maskView = maskView;
}
-(void)openAperture{
//Blur layer
CGRect frame = self.view.bounds;
CAShapeLayer *maskLayer = (CAShapeLayer *)self.visualEffectView.maskView.layer.mask;
//New path value
UIBezierPath *maskLayerPath = [UIBezierPath bezierPath];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:frame]];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRoundedRect:UIEdgeInsetsInsetRect(frame, UIEdgeInsetsMake(58, 15, 66, 15)) cornerRadius:1]];
[maskLayer setPath:maskLayerPath.CGPath];
//Animation
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"path"];
animation.delegate = self;
animation.duration = 0.44;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fromValue = (id)maskLayer.path;
animation.toValue = (id)maskLayerPath.CGPath;
[maskLayer addAnimation:animation forKey:#"animatePath"];
}
Apple Note About VisualEffectView issue on iOS 10
Transitions are tough in this realm, as maskView is the only way to
ensure that the effect works, but maskView also isn't animatable.
https://forums.developer.apple.com/message/184810#184810
The only the way to use "CAShapeLayer" as a mask is to apply your shape to UIView.layer.mask and then put it to UIVisualEffectView.maskView.
The maskView of UIVisualEffectView isn't animatable.
I have the same problem.
I tried to do next: (Swift code)
visualEffectView.layer.mask = maskView.layer.mask
instead of visualEffectView.mask = maskView
If so, path animation works fine, but then blur effect is gone.
If you find a solution, please update the post.

How to animate a drawn line in Objective C?

I am trying to animate drawn objects, for example I have drawn a line with this approach:
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(Center.x, Center.y)];
[path addLineToPoint:CGPointMake(Point.x,Point.y)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor whiteColor] CGColor];
shapeLayer.lineWidth = 1.5;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
[self.view.layer addSublayer:shapeLayer];
After a while I need to animate the line to have a different Point, but keeping Center as is, but I have no idea how to do that. Is my approach alright? Is there a better way to do so?
Solved it:
CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:#"path"];
morph.duration = 1.0;
UIBezierPath *path5 = [UIBezierPath bezierPath];
[path5 moveToPoint:CGPointMake(P22.x+5, P22.y+5)];
[path5 addLineToPoint:CGPointMake(P21.x,P21.y)];
morph.fromValue = (id) path.CGPath;
morph.toValue = (id) path5.CGPath;
[shapeLayer addAnimation:morph forKey:nil];
//next line to update the shapeLayer's new path
shapeLayer.path = path5.CGPath;

Gradient as circle stroke color in CAShapeLayer

CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(x, y, 100, 100) cornerRadius:50].CGPath;
// Configure the apperence of the circle
circle.fillColor = [UIColor whiteColor].CGColor;
circle.strokeColor = [UIColor darkGrayColor].CGColor;
circle.lineWidth = 1.8;
circle.lineDashPattern = #[#6, #3];
// Add to parent layer
[cell.layer addSublayer:circle];
I am using this code to draw a circle. Now, I want to use a gradient as stroke color. How can I do that?

Rounded corners on a view

I used the following method to get rounded corners on a view in my application:
(objective-c:)
hoursTable.layer.cornerRadius = 5.0;
[hoursTable setClipsToBounds:YES];
(my actual code is in rubymotion:)
self.view.layer.cornerRadius = 10
self.view.layer.masksToBounds = true
Now all the corners of that view are rounded with 10pt, how do I only apply the effect on the top-left and top-right corners and leave the bottom left and bottom right corner squared?
I have the category on UIView with this code:
- (void)setRoundedCorners:(UIRectCorner)corners radius:(CGSize)size {
UIBezierPath* maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:size];
CAShapeLayer* maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
[maskLayer release];
}
Remove the last line if you use ARC.
Example of usage:
[hoursTable setRoundedCorners:UIRectCornerTopLeft|UIRectCornerTopRight radius:CGSizeMake(5.0, 5.0)];
Try to create path manually
CAShapeLayer* shape = [CAShapeLayer layer];
CGMutablePathRef path = CGPathCreateMutable();
/*...*/
CGPathMoveToPoint(path, NULL, 0, 0);
/*create path for view*/
shape.path = path;
CGPathRelease(path);
view.layer.mask = shape;

How to draw a single rounded corner of my UIView.

Hi! I want to draw a rounded corner of my UIView. Only one, others cannot be changed.
Starting in iOS 3.2, you can use the functionality of UIBezierPaths to create an out-of-the-box rounded rect (where only corners you specify are rounded). You can then use this as the path of a CAShapeLayer, and use this as a mask for your view's layer:
// Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds
byRoundingCorners:UIRectCornerTopLeft
cornerRadii:CGSizeMake(10.0, 10.0)];
// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = imageView.bounds;
maskLayer.path = maskPath.CGPath;
// Set the newly created shape layer as the mask for the image view's layer
imageView.layer.mask = maskLayer;
And that's it - no messing around manually defining shapes in Core Graphics, no creating masking images in Photoshop. The layer doesn't even need invalidating. Applying the rounded corner or changing to a new corner is as simple as defining a new UIBezierPath and using its CGPath as the mask layer's path. The corners parameter of the bezierPathWithRoundedRect:byRoundingCorners:cornerRadii: method is a bitmask, and so multiple corners can be rounded by ORing them together.
NOTE - Layer masks will not render when used in combination with the CALayer renderInContext method. If you need to use this try rounding corners with the following: Just two rounded corners?.
I made a method of StuDev's answer:
+ (CAShapeLayer *) roundedCornerOnImage: (UIImageView *)imageView onCorner: (UIRectCorner)rectCorner
{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds
byRoundingCorners:rectCorner
cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = imageView.bounds;
maskLayer.path = maskPath.CGPath;
return maskLayer;
}
Example of usage on a imageview in a UITableViewCell:
if (indexPath.row == 0)
cell.imageView.layer.mask = [Helper roundedCornerOnImage:cell.imageView onCorner:UIRectCornerTopLeft];
else if (indexPath.row == self.arrayPeople.count - 1)
cell.imageView.layer.mask = [Helper roundedCornerOnImage:cell.imageView onCorner:UIRectCornerBottomLeft];
Thanks to StuDev for a great solution!
+ (CAShapeLayer *) roundedCornerOnImage: (UIImageView *)imageView onCorner: (UIRectCorner)rectCorner
{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds
byRoundingCorners:rectCorner
cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = imageView.bounds;
maskLayer.path = maskPath.CGPath;
imageView.layer.mask=maskLayer
return maskLayer;
}
if (indexPath.row == 0)
[Helper roundedCornerOnImage:cell.imageView onCorner:UIRectCornerTopLeft];
else if (indexPath.row == self.arrayPeople.count - 1)
[Helper roundedCornerOnImage:cell.imageView onCorner:UIRectCornerBottomLeft];
An updated answer to above , you dont need to return and manage that. It can be done in that function.
I have made a function for make the Custom corner radius after doing some small R&D as following:
+(void)setConerRadiusForTopLeft:(BOOL)isForTopLeft ForTopRight:(BOOL)isForTopRight ForBottomLeft:(BOOL)isForBottomLeft ForBottomRight:(BOOL)isForBottomRight withCornerRadius:(float)cornerRadius forView:(UIView *)view
{
UIRectCorner corners = (isForTopLeft ? UIRectCornerTopLeft : 0) |
(isForTopRight ? UIRectCornerTopRight : 0) |
(isForBottomLeft ? UIRectCornerBottomLeft : 0) |
(isForBottomRight ? UIRectCornerBottomRight : 0);
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds
byRoundingCorners:corners
cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = view.bounds;
maskLayer.path = maskPath.CGPath;
view.layer.mask = maskLayer;
}