Safari-style gradient shadows around UIScrollView
I've been looking to embellishing a UIScrollView by adding some kind of shadow around the content, visible when the view is greater than the content. Safari does this using grey gradients around the page (pinch to make a webpage smaller and pan to see the gradients at the edges)
There are lots of discussions on a similar topic but they all seem to discuss solutions for UITableView (gradients above and below the content), not UIScrollView which requires gradients around all four edges.
I initially used a layer effect (see below) but this visibly affected performance and pan & zoom became jumpy, especially with Retina display, so I removed it.
ChartView *chartView = [[ChartView alloc] initWithChild:child type:type];
// Give it a nice shadow -- Unfortunately this kills performance, especially on Retina phones
aChartView.layer.masksToBounds = NO;
aChartView.layer.shadowOffset = CGSizeMake(10, 12);
aChartView.layer.shadowRadius = 20;
aChartView.layer.shadowOpacity = 0.6;
// Create the scroll view (root view)
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; // Allow automatic resizing in orientation changes
scrollView.backgroundColor = [UIColor lightGrayColor];
scrollView.delegate = self;
[scrollVi开发者_高级运维ew addSubview:chartView];
I tried subclassing UIScrollView and overriding drawRect and was able to draw a background, but it only gets called once so I cannot adjust the background as the content moves/resizes.
Safari doesn't use a shadow, but some kind of gradient (which, incidentally, look slightly imperfect at the corners if you look very carefully), maybe this gives better perf. Anybody knows how they do this?
EDIT
This issue is now resolved and I have put my implementation of this (a subclass of UIScrollView which adds Safari-style gradient shadows to it) on GitHub for readers who are looking for the same thing: https://github.com/Clafou/ShadowedScrollView
I think you're right that the corners are the problem. I know that using layer.cornerRadius really kills performance and I would assume that shadowRadius probably does, too.
Possibly the better option is to do what it looks like Safari does, which is add a CAGradientLayer on all four sides. With Safari, they started the gradient behind the view so that the corners would still be shaded, but it has the side effect of making them look a little weird. However, this is probably the least graphically intensive way to do it.
Finding an example for a CAGradientLayer is pretty easy. The default is a vertical gradient. To make it a horizontal gradient, just set the start and end points:
gradient.startPoint = CGPointMake(0, 0.5);
gradient.endPoint = CGPointMake(1.0, 0.5);
There is a much simpler answer to the performance problem - simply set a shadow path matching the outline of the view:
aChartView.layer.shadowPath = [UIBezierPath bezierPathWithRect:aChartView.bounds].CGPath;
精彩评论