在 iOS 上做阴影的最快方法是啥?
Posted
技术标签:
【中文标题】在 iOS 上做阴影的最快方法是啥?【英文标题】:Fastest way to do shadows on iOS?在 iOS 上做阴影的最快方法是什么? 【发布时间】:2012-04-12 23:08:16 【问题描述】:QuartzCore .layer.shadow 的性能提升。每次发生变化时,它们似乎都需要重新渲染,从而导致一切滞后。
Coregraphics 渐变(用于 1 路阴影) - 看起来不正确。如果您的渐变从 0.3 alpha 变为 0,它会产生一些奇怪的效果,您可以“看到”它停止。就是不好看,也不自然。也许它没有抖动,但我确信我听说核心图形渐变是。很奇怪,我不知道。
Coregraphics 阴影 - 设置它们时需要一段时间来渲染,但除此之外性能非常好。就在您等待视图出现的那一刻,因为它必须首先渲染它的阴影,这就是问题所在。
所以我一定错过了什么。是否有另一种看起来正确且渲染时间和性能都很快的方法?
【问题讨论】:
【参考方案1】:添加 shadowPath 应该会给您带来巨大的性能提升。以下示例假设您只想要视图两侧的阴影
CGPathRef path = [UIBezierPath bezierPathWithRect:view.bounds].CGPath;
[view.layer setShadowPath:path];
编辑: 默认情况下,CALayer 在动画期间绘制阴影,以下代码允许您将阴影缓存为位图并重复使用它而不是重新绘制它:
self.view.layer.shouldRasterize = YES;
// Don't forget the rasterization scale
// I spent days trying to figure out why retina display assets weren't working as expected
self.view.layer.rasterizationScale = [UIScreen mainScreen].scale;
【讨论】:
rasterizationScale 也引起了我的注意!你会想象它会默认基于屏幕比例,但不是。 :-/ 我有一个部分透明的 PNG,带有锯齿状的边缘,我必须对其进行动画处理(当然是阴影)。它的大小是屏幕的 2/3,所以有不少像素。该解决方案仍然完美无缺。 :) 别忘了将rasterizationScale
设置为主屏幕的边界,否则生成的BMP 将是拉伸的非Retina 视图(很难看)...
EDIT:我的意思是这是对我有用的解决方案,而 shadowPath
对我的性能没有影响。
你是个天才。 @chklbumper 您是否使用旧 iPhone 进行测试? iPhone 5 快速渲染shadowOffset
阴影,但iPhone 4 在绘制shadowOffset
阴影时出现滞后和故障。【参考方案2】:
我经常看到人们使用 HUGE 性能影响视图的图层来创建圆角或阴影。像这样的:
[v.layer setCornerRadius:30.0f];
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[v.layer setBorderWidth:1.5f];
[v.layer setShadowColor:[UIColor blackColor].CGColor];
[v.layer setShadowOpacity:0.8];
[v.layer setShadowRadius:3.0];
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)];
.....
这对性能有巨大的影响,尤其是阴影。将这样的视图放在 UITableView 中(或事实上任何移动的东西)将创建一个 android-ish 滚动体验,你不希望这样。如果您需要动画或移动视图,请避免创建圆角或这样的阴影!
认识核心图形 我创建了一个简单的 UIView 子类来向您展示如何以稍微不同的方式实现相同的结果。它使用 Core Graphics 来绘制视图,与上面的代码相比,它不会影响性能。
这是绘图代码:
- (void)drawRect:(CGRect)rect
CGContextRef ref = UIGraphicsGetCurrentContext();
/* We can only draw inside our view, so we need to inset the actual 'rounded content' */
CGRect contentRect = CGRectInset(rect, _shadowRadius, _shadowRadius);
/* Create the rounded path and fill it */
UIBezierPath *roundedPath = [UIBezierPath bezierPathWithRoundedRect:contentRect cornerRadius:_cornerRadius];
CGContextSetFillColorWithColor(ref, _fillColor.CGColor);
CGContextSetShadowWithColor(ref, CGSizeMake(0.0, 0.0), _shadowRadius, _shadowColor.CGColor);
[roundedPath fill];
/* Draw a subtle white line at the top of the view */
[roundedPath addClip];
CGContextSetStrokeColorWithColor(ref, [UIColor colorWithWhite:1.0 alpha:0.6].CGColor);
CGContextSetBlendMode(ref, kCGBlendModeOverlay);
CGContextMoveToPoint(ref, CGRectGetMinX(contentRect), CGRectGetMinY(contentRect)+0.5);
CGContextAddLineToPoint(ref, CGRectGetMaxX(contentRect), CGRectGetMinY(contentRect)+0.5);
CGContextStrokePath(ref);
查看此博客: http://damir.me/rounded-uiview-with-shadow-the-right-way
【讨论】:
此博客中指向 git 存储库的链接似乎不再有效。我应该如何在 UICollectionViewCell 上使用它? 在 UICollectionViewCell @trdavidson 的子类中添加上面的drawrect 我一直在玩这个代码,并且遇到以下问题:单元格中的子视图没有被裁剪,使得角落中的视图仍然与圆角重叠。此外,在滚动时,某些单元格似乎“丢失”并且根本没有得到阴影层。对可能导致这种情况的任何想法? 确保在数据源委托@trdavidson 中调用 [yourcell setNeedsToDisplay] 以查看您的问题是否仍然存在 哪个性能更好?从包中加载 UIImage(小于 1kb)或使用 UIBezierPath 绘制?以上是关于在 iOS 上做阴影的最快方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章