Shadow on sublayer of CAGradientLayer - objective-c

I have a CALayer as a sublayer to a CAGradientLayer and I find that shadows do not render. I'm wondering if someone has done this successfully?
Heres my implementation:
CAGradientLayer *root;
// set up root with gradient
// gradient displays well
[self.layer addSublayer:root];
CALayer *menuBox = [CALayer layer];
menuBox.backgroundColor = [UIColor whiteColor].CGColor;
menuBox.frame = CGRectInset(root.frame, 20, 20);
menuBox.cornerRadius = 15.0;
menuBox.masksToBounds = YES;
menuBox.shadowColor = [UIColor greenColor].CGColor;
menuBox.shadowOffset = CGSizeMake(4.0,6.0);
menuBox.shadowOpacity = 1.0;
menuBox.shadowRadius = 4.0;
//add sublayers to root in correct order, bottom first
[root addSublayer:menuBox];
I display a rounded white rectangle over a gradient background. I want the white rectangle to have a shadow, but none appears.
Any tips?

Related

Add border colour to UIButton Bezeir path

UIButton corners only two sides i.e. top right and bottom right with following:
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:_nearmeButton.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerBottomLeft) cornerRadii:CGSizeMake(20.0, 20.0)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.view.bounds;
maskLayer.path = maskPath.CGPath;
_nearmeButton.layer.mask = maskLayer;
But how to give border colour to above UIButton same as given image .
You are on the right track. Instead of setting your path as a mask you can add it to the buttons layer. Basically (more or less) every UIView is backed by a CALayer. Just set the colors you want on the stroke and the fill and add it to the buttons layer, and you are done.
UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:_nearmeButton.bounds byRoundingCorners:(UIRectCornerTopRight | UIRectCornerBottomRight) cornerRadii:CGSizeMake(20.0, 20.0)];
CAShapeLayer *borderLayer = [[CAShapeLayer alloc] init];
borderLayer.frame = self.view.bounds;
borderLayer.path = borderPath.CGPath;
borderLayer.strokeColor = [UIColor redColor].CGColor;
borderLayer.fillColor = [UIColor clearColor].CGColor;
borderLayer.lineWidth = 1.0;
[_nearmeButton.layer addSublayer:borderLayer];
If your buttons size changes you need to update the layer size also.

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.

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?

2D Rotation of CALayer with UIBezierPath

I'm trying to rotate a CALayer which is composed of UIBezierPath. The display is great.
CALayer* layer = [CALayer layer];
CAShapeLayer *shapeView = [[CAShapeLayer alloc] init];
UIBezierPath *arc = [UIBezierPath bezierPath];
[arc moveToPoint:CGPointMake(center.x + obj1.startx * cos(obj1.angle), center.y + obj1.starty * cos(obj1.angle))];
[shapeView setPath:arc.CGPath];
[layer addSublayer:shapeView];
// Rotation
layer.transform = CATransform3DMakeRotation(angle, 0, 0, 1);
But the CATransform3DmakeRotation rotate the CAShape around the point (0,0) I guess.
I tried to set the anchorPoint to the center of the view but it's not working better.
It seems that the CAlayer has no content because its height and width are equal to zero.
What did I do wrong ?
Thanks

Make area around masked region transparent with CALayers?

I'm trying to crop an image to an irregular shape, but I need to make the area that was removed transparent.
Inside subclass of UIView
CALayer *myLayer = [CALayer layer];
CAShapeLayer *mask = [CAShapeLayer layer];
myLayer.frame = self.bounds;
myLayer.contents = (id)[self.picture CGImage];
mask.path = path;
myLayer.mask = mask;
[self.layer addSublayer:myLayer];
This will crop the image appropriately, but the background color of the view is white and therefore still visible. I've tried making the other layers transparent, but it has not worked.
(self and subview both refer to same view)
[self layer].backgroundColor = [UIColor clearColor].CGColor //no change
[self layer].opacity = 0; //makes entire view transparent
subView.backgroundColor = [UIColor clearColor]; // entire view becomes transparent
Is it possible to create the effect I'm trying to achieve?
I tried the same thing, here is the exact code:
// In KMViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
CGRect frame = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
KMView *view = [[KMView alloc] initWithFrame:frame];
view.center = self.view.center;
[self.view addSubview:view];
}
// In KMView.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// self.backgroundColor = [UIColor clearColor];
CALayer *layer = [CALayer layer];
CAShapeLayer *mask = [CAShapeLayer layer];
layer.frame = self.bounds;
UIImage *image = [UIImage imageNamed:#"orange"];
layer.contents = (id)image.CGImage;
CGPathRef path = CGPathCreateWithEllipseInRect(frame, NULL);
mask.path = path;
CGPathRelease(path);
layer.mask = mask;
[self.layer addSublayer:layer];
}
return self;
}
It worked for me as expected. The background was transparent. Then I tried adding
self.backgroundColor = [UIColor clearColor];
to the beginning of the code and nothing changed, the image was showing on a transparent background clipped to the path.
I think the problem might be somewhere else.