Reputation: 2570
In a custom tableview cell, I'm drawing a simple rectangle with a shadow like this:
photoBorder = [[[UIView alloc] initWithFrame:CGRectMake(4, 4, self.frame.size.width-8, 190)] autorelease];
photoBorder.autoresizingMask = UIViewAutoresizingFlexibleWidth;
photoBorder.backgroundColor = [UIColor whiteColor];
photoBorder.layer.masksToBounds = NO;
photoBorder.layer.shadowOffset = CGSizeMake(0, 1);
photoBorder.layer.shadowRadius = 4;
photoBorder.layer.shadowOpacity = 1.0;
photoBorder.layer.shadowColor = [UIColor darkGrayColor].CGColor;
photoBorder.layer.shouldRasterize = YES;
photoBorder.layer.shadowPath = [UIBezierPath bezierPathWithRect:photoBorder.bounds].CGPath; // this line seems to be causing the problem
This works fine when the view first loads. However, when you rotate the device, the shadow stays the same size. I'd really like it to stretch to the new width of "photoBorder".
I can get it to work by removing the shadowPath, but the tableview takes a noticeable performance hit.
Anyone have any tips on making a shadow, on a UIView, that can stretch, without losing performance?
Upvotes: 2
Views: 2011
Reputation: 8395
You need to create a subclass of UIView so that you can get the new bounds in the layoutSubviews()
method.
Note: If you try to add this code in a ViewController that owns the subview, the bounds will remain static as you rotate, which results in the wrong shadowPath.
import UIKit
class BackgroundView: UIView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
updateShadow(on: self)
}
func updateShadow(on background: UIView) {
let layer = background.layer
layer.shadowPath = UIBezierPath(rect: background.bounds).cgPath
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowRadius = 4
layer.shadowOpacity = 0.22
}
}
Make sure you call super.layoutSubviews()
to handle any Auto Layout constraints.
You can set a custom class in a Storyboard file.
Upvotes: 3
Reputation: 2570
After searching for a few hours and not finding anything, I posted this. Then found an answer a few minutes later.
The simple solution for me appears to be simply moving the shadowPath into layoutSubviews.
- (void)layoutSubviews{
photoBorder.layer.shadowPath = [UIBezierPath bezierPathWithRect:photoBorder.bounds].CGPath;
}
Upvotes: 6
Reputation: 1412
for performance enhancement you can draw an inner shadow using Core Graphics.
Inner shadow effect on UIView layer
Upvotes: 0