Thursday, April 21, 2016

Apply CAShapeLayer to main UIView except UIButton

Leave a Comment

Here is a code which applying mask to the whole UIView:

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:self.view.bounds]; [maskPath appendPath:[UIBezierPath bezierPathWithArcCenter:self.mapCardsButton.center                                                     radius:self.mapCardsButton.frame.size.height/2.0f                                                 startAngle:0.0f                                                   endAngle:2.0f*M_PI                                                  clockwise:NO]]; CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.fillRule  = kCAFillRuleEvenOdd; maskLayer.fillColor = [UIColor blackColor].CGColor; maskLayer.path = maskPath.CGPath; self.view.layer.mask = maskLayer; 

The problem is that I want to apply the mask above to the whole UIView except one specific UIButton(mapCardsButton) which is also on the same UIView. Is it possible to do?

UPD: I tried

[self.view.layer insertSublayer:maskLayer atIndex:0]; 

instead of

self.view.layer.mask = maskLayer; 

but my self.view lost alpha channel and animation of maskLayer doesn't work anymore

Here is a project with code: https://www.dropbox.com/s/b94qcwxzoi23kwk/test_04092016.zip?dl=0

2 Answers

Answers 1

The simplest way would be for the UIButton to be a sibling view of the masked view, rather than a subview. I realise that it might make logical sense for the button to be a subview (especially since it looks like your code is probably from a UIViewController subclass), so I would create a container UIView that holds all the other subviews apart from mapCardsButton and apply the mask to this new view.

So say you called the new view maskedContainerView, then:

  • self.view has two subviews: maskedContainerView and mapCardsButton
  • maskedContainerView holds all the subviews that self.view used to, except mapCardsButton
  • maskedContainerView.layer.mask = maskLayer.

Answers 2

Why don't you try the following? instead of the following stack:

• mask(view) -> button

make the view background color clear, at an additional subview and do the following:

• view -> mask(subView), button

This way you will have the same visual effect, but use the bottom view as a container. In code:

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:self.view.bounds]; [maskPath appendPath:[UIBezierPath bezierPathWithArcCenter:self.mapCardsButton.center                                                     radius:self.mapCardsButton.frame.size.height/2.0f                                                 startAngle:0.0f                                                   endAngle:2.0f*M_PI                                                  clockwise:NO]]; CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.fillRule  = kCAFillRuleEvenOdd; maskLayer.fillColor = [UIColor blackColor].CGColor; maskLayer.path = maskPath.CGPath;  UIView *maskedView = [[UIView alloc] initWithFrame:self.view.bounds];     maskedView.mask = maskLayer;  self.view.backgroundColor = [UIColor clearColor]; [self.view addSubView:maskedView]; [self.view addSubView:self.mapCardsButton]; 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment