圆角与阴影

结论

masksToBounds = true + cornerRadius > 0 (常见的设置圆角手段)
cornerRadius 的文档中明确说明对 cornerRadius 的设置只对 CALayer 的 backgroundColor 和 borderWidth&borderColor 起作用,如果 contents 有内容或者内容的背景不是透明的话,只有设置 masksToBounds 为 true 才能起作用,此时两个属性相结合,容易产生离屏渲染,不是一定会产生离屏渲染。


iOS 9.0 之后UIImageView里png图片设置圆角不会触发离屏渲染了, 也不需要设置layer.masksToBounds = YES了。
但是如果UIImageView有背景色,那么还会造成离屏渲染。
UIButton设置了backgroundImageView,设置圆角仍然需要layer.masksToBounds = YES,并且会造成离屏渲染。
UIButton设置imageView圆角 _btn.imageView.layer.cornerRadius = xx;不需要设置layer.masksToBounds = YES,也不会造成离屏渲染。


前言

我一直都以为用cornerRadius设置的圆角和阴影不能在同一个view上共同存在,最近才发现并不是每个view都这样。

在这里插入图片描述

从左到右分别是UIView,UIButton,UILabel,UIImageView

在这里插入图片描述

可以看到UIView和UIButton设置圆角不需要设置masksToBounds = YES,而UILabel和UIImageView则需要设置了才能有圆角。

在这里插入图片描述
下面给这些view加阴影
在这里插入图片描述

设置了masksToBounds = YES的view没有阴影。
在这里插入图片描述

所以并不是所有的view设置圆角都需要设置masksToBounds = YES的,在UIView和UIButton上(用cornerRadius设置)圆角和阴影是可以共存的。


今天看到了一下新的label圆角的解决方案,cornerRadius属性是影像layer显示的backgroundColor和border的,对layer的contents不起作用。

对于不需要设置backgroundColor的label,只设置borderWidth、borderColor的label,直接设置cornerRadius,不需要设置masksToBounds=YES,就可以直接实现圆角功能。

d对于需要同时设置backgroundColor的label,直接设置cornerRadius是不能正确显示圆角的,原因是:UIabel设置backgroundColor的行为不再是设置layer的背景色而是为contents设置背景色。所以解决方式是我们不去设置label的backgroundColor,而是直接设置label.layer.backgroundColor,这样就可以直接单独设置cornerRadius,显示圆角的效果。

给UILabel和UIImageView同时添加圆角和阴影

以label为例
在这里插入图片描述

关于圆角影响性能的问题

上述代码在没有添加阴影之前,如果你勾选上Color Off-screen rendered,就会发现label 和imageView四周出现了黄色的标记,说明这里出现了离屏渲染。
需要强调的一点是,离屏渲染并非由设置圆角导致的!上述的aView和btn并没有出现离屏渲染,说明并不是cornerRadius导致的离屏渲染,而单独设置masksToBounds(下面没有特别提醒,masksToBounds都代表masksToBounds = YES)也不会产生离屏渲染,如果是UIView或者UIButton,UILabel同时设置这两个属性也不会产生离屏渲染,只有UIImageView同时设置这两个属性才会产生离屏渲染,从而影响性能。
会产生离屏渲染:✅
不会产生离屏渲染:❎

cornerRadius = xmasksToBounds = YEScornerRadius = x && masksToBounds = YES
UIView
UIButton
UILabel
UIImageView

注意:

  • UIButton设置了图片的时候设置圆角的时候也会出现离屏渲染。
  • 在tableview和collection的cell上试验,发现cell上只有button设置图片同时设置圆角的时候才会发生离屏渲染,其他的view都不会发生离屏渲染包括UIImageView。
  • 设置阴影,设置了 shadowPath就不会产生离屏 渲染 。

虽然设置masksToBounds会导致离屏渲染,从而影响性能,但是这个影响到底会有多大?在我的 iPhone6 上,即使出现了 17 个带有圆角的视图,滑动时的帧数依然在 58 - 59 fps 左右波动。
然而,这并非说明 iOS 9 做了什么特殊优化,或者是离屏渲染的影响不大,其主要原因在于圆角不够多。当我将一个 UIImageView 也设置成圆角,也就是屏幕上的圆角视图达到 34 个时,fps 大幅度下降,大约只有 33 左右。基本上已经达到了影响用户体验的范围。因此,一切不讲依据的优化都是耍流氓,如果你的圆角视图不多,cell 不复杂,就不要费力气折腾了。

还有一点要强调设置阴影也是会发生离屏渲染的,谨慎使用。 设置阴影路径,layer.shadowPath可以避免发生离屏渲染

如何高效的设置圆角

如果是UIView和UIButton设置圆角使用cornerRadius就可以了,经过验证UICollectionViewCell和UITablevViewCell同样可以使用在这个属性设置圆角而且不需要设置masksToBounds。其他的view,如UILabel,UIImageView

使用CAShapeLayer和UIBezierPath设置圆角(对内存消耗小,渲染速度快。),mask同样会触发离屏渲染,但是对内存的消耗最少,而且渲染快速
在这里插入图片描述
使用UIBezierPath和Core Graphics 框架画出一个圆角(只适用于UIImageView的方法)
在这里插入图片描述

总结:

  • 如果能够只用cornerRadius解决问题,就不用优化。
  • 如果必须设置masksToBounds,可以参考圆角视图的数量,如果数量较少(一页只有几个)也可以考虑不用优化。
  • UIImageView的圆角通过UIBezierPath和Core Graphics实现,其他视图的圆角可以通过UIBezierPath和CAShapeLayer画出圆角矩形实现。

参考:
http://www.cocoachina.com/ios/20160301/15486.html


今天在项目中遇到个问题,给collection的cell加阴影和圆角的时候圆角生效了,阴影不生效。这很奇怪,之前这么做都是有效果的。

cell.layer.cornerRadius = 10;
cell.layer.shadowColor = [UIColor yellowColor].CGColor;
cell.layer.shadowOpacity = 0.9;
cell.layer.shadowRadius = 5;
cell.layer.shadowOffset = CGSizeMake(-1, -1);

我分析了一下这个cell与其他cell的不同,最大的不同就是这个cell是xib写的。难道是xib的cell阴影的代码需要在特定的位置写吗?
尝试了几种方法一直都没用,甚至一度放弃这种实现方式,但是其他的方式出来得UI又不太完美,只能继续研究。
我突发奇想加了一句cell.layer.masksToBounds = NO;,然年阴影就出现了。
这就有些奇怪了,按道理讲masksToBounds默认是NO,难道这里她cell默认是YES的吗,打印了一下masksToBounds,发现确实masksToBounds在xib的cell是true的。
又去测试了一下tableview的cell,table的cell没有这种情况的出现,不管是xib还是纯代码cell的masksToBounds都是NO。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值