Why Maskstobounds = Yes Prevents Calayer Shadow

Why masksToBounds = YES prevents CALayer shadow?

Because shadow is an effect done outside the View, and that masksToBounds set to YES will tell the UIView not to draw anything that is outside itself.

If you want a roundedCorner view with shadow I suggest you do it with 2 views:

UIView *view1 = [[UIView alloc] init];
UIView *view2 = [[UIView alloc] init];

view1.layer.cornerRadius = 5.0;
view1.layer.masksToBounds = YES;
view2.layer.cornerRadius = 5.0;
view2.layer.shadowColor = [[UIColor blackColor] CGColor];
view2.layer.shadowOpacity = 1.0;
view2.layer.shadowRadius = 10.0;
view2.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
[view2 addSubview:view1];
[view1 release];

Stop CALayer shadow from affecting subviews?

This happens when parent view has alpha less than 1.0 or has no background color (i.e is set to clear color). In that case shadow translates to subviews. See my answer here for more details.

Apple Docs prove this:

Figure A-7 shows several different versions of the same sample layer
with a red shadow applied. The left and middle versions include a
background color so the shadow appears only around the border of the
layer. However, the version on the right does not include a background
color. In this case, the shadow is applied to the layer’s content,
border, and sublayers.

Shadow

Can't add a corner radius and a shadow

Yes, yes there is...

If you want both a corner radius and a drop shadow, you don't turn on -masksToBounds, but rather set the corner radius and set the bezier path of the shadow with a rounded rect. Keep the radius of the two the same:

[layer setShadowOffset:CGSizeMake(0, 3)];
[layer setShadowOpacity:0.4];
[layer setShadowRadius:3.0f];
[layer setShouldRasterize:YES];

[layer setCornerRadius:12.0f];
[layer setShadowPath:
[[UIBezierPath bezierPathWithRoundedRect:[self bounds]
cornerRadius:12.0f] CGPath]];

You might want to check your performance without the -shouldRasterize parameter set once you're setting the shadow path. Drawing performance tends to be very good once you've set a shadow path.

UPDATE

I hadn't looked at this problem in quite awhile, but it appears that you no longer need to set a shadowPath in order to get this to work. Simply setting the cornerRadius and shadowOpacity will work now. I think this has been the case since iOS5 (as far as I can tell). Providing this update is probably unnecessary since setting those parameters 'just works', but I'll provide it for posterity sake. To recap, this is now all you need:

[layer setShadowOpacity:0.4];
[layer setCornerRadius:12.0f];

If you still need better performance, you can go ahead and set the shouldRasterize parameter as well:

[layer setShouldRasterize:YES];

And speaking of performance, it's worth noting that if you are noticing sluggish animations, you will want to use the technique of setting the shadow path after all. This update was really just to point out that setting the path is no longer required to achieve the effect of displaying both a corner radius and a shadow at the same time. If performance is your priority, though, use a path.

UPDATE 2

Since people seem to be having trouble getting this to work in some instances, I'll post a more complete code snippet here from a sample project I created:

- (void)viewDidLoad
{
[super viewDidLoad];

CALayer *layer = [CALayer layer];
[layer setBounds:CGRectMake(0.0f, 0.0f, 100.0f, 200.0f)];
[layer setPosition:[[self view] center]];
[layer setBackgroundColor:[[UIColor lightGrayColor] CGColor]];
[layer setShadowOpacity:0.55f];
[layer setCornerRadius:8.0f];
[layer setBorderWidth:1.0f];

[[[self view] layer] addSublayer:layer];

[[[self testView] layer] setShadowOpacity:0.55f];
[[[self testView] layer] setShadowRadius:15.0f];
[[[self testView] layer] setCornerRadius:8.0f];
[[[self testView] layer] setBorderWidth:1.0f];
}

The testView is a UIView I added in Interface Builder and set an outlet on. This is to make sure it's working the same on both layers you add explicitly as well as the layers within subviews.

I've tested this on the simulators for iOS5 through iOS6.1. It gives this result for me in each of them:

Sample Image

Why is my CALayer shadow blurry on retina displays when using shadowPath with shadowRadius set to 0?

As of iOS 9.0 the contentsScale property of CALayer will also affect the rasterization scale of shadowPath. In other words, setting layer's contentsScale to screen scale will fix your issue.

Can't set cornerRadius AND shadow on layer that has an image view stretched to its bounds?

You will need two nested views, the inner one setting rounded corners and clipping to bound, and the outer view having the shadow (and therefore not clipping). In your case inner and outer view will probably be "child" and "parent", but I guess you didn't set the right clipping values for these views?

See the answer in Why masksToBounds = YES prevents CALayer shadow?.



Related Topics



Leave a reply



Submit