3

有没有办法在不执行以下任何操作的情况下绘制圆形 UIImages?

  1. 混合(Core Animation Instruments 中的红色)
  2. 离屏渲染(Core Animation Instruments 中的黄色)
  3. 绘制矩形

我试过了

  1. 带有剪切路径的drawRect。这太慢了。(见:http: //developer.apple.com/library/ios/#qa/qa1708/_index.html
  2. 带有 maskLayer 的 CALayer 内容。这引入了离屏渲染。
  3. UIImageView 和设置cornerRadius 和maskToBounds。这与#2具有相同的效果。

我最后的手段是直接修改图像。有什么建议么?

4

2 回答 2

3

我使用blog.sallarp.com 的圆角算法的变体。我将我的修改为仅圆某些角落,它是无缝集成的类别,但该链接为您提供了基本概念。我认为这可能符合“屏幕外渲染”的条件,这是您拒绝的技术之一,但我并不完全确定。我从未见过任何可观察到的性能问题,但也许您遇到了一些特殊情况。

你能在你的图像视图上覆盖一个只有角落的图像视图,以呈现圆角的外观吗?

或者,如果您担心圆角会导致性能下降,为什么不让您的应用程序保存带有圆角的图像副本,这样您只能在第一次获得性能?这相当于您的“直接修改图像”的概念,但要及时进行。

更新:

底线,我不知道任何其他解决方案(缺少我笨拙的想法,下面的第 2 点)。但我做了一些实验(因为我正在处理类似的问题)并得出以下结论:

  1. 如果您在 3GS 或更高版本的设备上具有圆角性能,则问题可能不在圆角上。我发现虽然它对 3G 上的 UI 产生了重大影响,但在 3GS 上几乎不明显,而在后来的设备上则难以察觉。如果您从圆角看到性能问题,请确保是圆角而不是其他问题。我发现,如果我对以前缓存的图像进行即时舍入,舍入的影响可以忽略不计。(当我在缓存之前进行四舍五入时,UI 就像丝绸一样光滑。)

  2. 遮罩的替代方法是创建一个反转圆角的图像(即,它与角落中的背景匹配,在您希望图像显示的地方透明),然后将此图像放在 tableviewcell 的图像前面. 我发现,要让它工作,我必须使用自定义单元格(例如,创建我自己的主图像视图控件、我自己的标签,加上这个角遮罩图像视图控件),但它肯定比即时更好调用圆角算法。如果您试图在分组表中圆角,这可能效果不佳,但如果您只是想要圆角的外观而不实际圆角,这是一个可爱的小技巧。

  3. 如果您因为使用分组表格视图而圆角并且您不喜欢图像溢出圆角,您可以简单地将第一行图像的左上角和最后一个图像的左下角. 这将减少圆角逻辑的调用。它看起来也不错。

  4. 我知道你没有问过这个问题,但是关于 tableviews 中图像的其他可能的性能问题包括:

    • 如果您使用类似imageWithContentsOfFile(不缓存) in 的东西cellForRowAtIndexPath,您肯定会看到性能问题。如果您不能利用imageNamed缓存(无论如何有些人抱怨它),您可以自己缓存您的图像,无论是即时缓存还是提前在辅助线程上预加载它们。如果您的 tableview 引用了以前加载的图像并且您会看到巨大的性能改进,那么圆角可能会或可能不会仍然是一个问题。

    • 其他性能问题的来源包括使用的图像不是为您的 tableview 的 imageview 优化大小的。大图像对性能产生了巨大影响。

  5. 底线,

    • 在你在这里自杀之前,确保舍入是唯一的性能问题。如果您在当代硬件上看到问题,则尤其如此,因为根据我的经验,影响可以忽略不计。另外,如果有一个更广泛的解决方案会更好,那么在这个问题上浪费太多睡眠将是一种耻辱。使用不是尺寸优化的缩略图的图像、缓存图像失败等都会对性能产生巨大影响。

    • 如果可能的话,提前把图像的角落弄圆,UI 会是最好的,并且视图控制器的代码会很好很简单。

    • 如果您不能提前做到这一点(例如,因为您正在实时下载图像),您可以尝试角落遮蔽图像技巧,但这仅在某些情况下有效(尽管非分组的 tableview 是其中之一)。

    • 如果您必须在 UI 进行时进行圆角,请在单独的队列中进行圆角并且不要阻塞 UI。

于 2012-07-04T01:48:56.727 回答
1

这就是我所做的,我通常对它的表现感到满意:

UIImageView *iv=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"769-male"]];
UIGraphicsBeginImageContextWithOptions(iv.bounds.size, NO, [UIScreen mainScreen].scale);
[[UIBezierPath bezierPathWithRoundedRect:v.bounds cornerRadius:s] addClip];
[image drawInRect:v.bounds];
v.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
于 2014-01-17T00:06:59.030 回答