本片文章前三章内容你们比较经常使用,后面的可能会不那么经常使用,前面的基础内容不想看了能够直接从第4段开始html
这个功能仍是很常见的,原本不想记了,为了整个系列的完整性,仍是啰嗦一下。
CALayer
有一个conrnerRadius
的属性控制图层的圆角曲率,默认值为0。这个曲率值默认只影响背景颜色而不影响背景图片或者子图层。能够用过下面的示例看一下。ios
在Storyboard
中放置两个白色的view
,每一个view
分别有两个子view
(一个黄色,一个青色),并且都超出了父视图的边界:git
而后在代码中写入以下代码:性能
@interface ViewController () @property (weak, nonatomic) IBOutlet UIView *leftView; @property (weak, nonatomic) IBOutlet UIView *rightView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.leftView.layer.cornerRadius = 20.f; self.rightView.layer.cornerRadius = 20.f; self.rightView.layer.masksToBounds = YES; } @end
而后运行效果以下:动画
经过上面的示例能够发现:atom
cornerRadius
时,默认状况下,只影响背景颜色,而不影响背景图片或者子图层。masksToBounds
为YES
。CALayer
另外两个很是有用的属性borderWidth
和borderColor
。borderWidth
是以点为单位定义边框粗细的浮点数,默认为0。borderColor
定义了边框的颜色,默认为黑色。spa
borderColor
是CGColorRef
类型。
边框绘制在图层边界里面,在全部子图层以前。对上面的示例代码坐下调整:指针
- (void)viewDidLoad { [super viewDidLoad]; self.leftView.layer.cornerRadius = 20.f; self.rightView.layer.cornerRadius = 20.f; self.leftView.layer.borderWidth = 5.f; self.rightView.layer.borderWidth = 5.f; self.rightView.layer.masksToBounds = YES; }
运行效果以下:code
如上面的示例的结果同样,边框并不会把寄宿图或子图层的相撞计算出来。并且绘制边框会显示在最上层。
控制图层阴影的属性会比前面的边框多一些。htm
shadowOpacity
属性控制阴影透明度的,它是一个在0.0
和1.0
之间的浮点数,若是设置为1.0
将会显示一个轻微模糊的阴影。shadowColor
属性控制着阴影的颜色,和borderColor
同样,它的类型也是CGColorRef
,阴影默认是黑色的。shadowOffset
属性控制阴影的方向和距离,它是一个CGSize
的值,宽度控制阴影横向位移,高度控制纵向位移。默认值是`{0, -3}。shadowRadius
属性控制着阴影的模糊度,当值为0
的时候,阴影和视图同样有一个明显的边界,值越大,边界线看起来就会越模糊。和图层边框不一样,图层的阴影继承自内容的外形,而不是根据边界来界定。
有个头疼的限制,阴影一般在Layer
的边界以外,若是咱们开启了maskToBounds
以后,全部突出图层外的内容都会被裁剪到,包括咱们设置的阴影。
以前有个UI需求,同时设置阴影和圆角,圆角简单的使用layer.cornerRadius
和maskToBounds
。致使一直显示不出来阴影,差的缘由是没法共存,到如今才发现是maskToBounds
致使的。
maskToBounds
把阴影也裁掉的结果确定不是咱们想要的。可是在同一个图层缺又存在这个问题,因此这看起来很简单的效果,咱们须要用到两个图层,一个图层作maskToBounds
裁剪,一个图层画阴影。
下面咱们用圆角下面的那个demo稍做修改作个示例:
首先对rightView
作一个透明色的shadowView
的包裹,用来设置阴影:
将代码修改为以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIView *leftView; @property (weak, nonatomic) IBOutlet UIView *rightView; @property (weak, nonatomic) IBOutlet UIView *shadowView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.leftView.layer.cornerRadius = 20.f; self.rightView.layer.cornerRadius = 20.f; self.leftView.layer.borderWidth = 5.f; self.rightView.layer.borderWidth = 5.f; // 不添加其余图层直接给 leftView 设置阴影试一试 self.leftView.layer.shadowOffset = CGSizeMake(5, 5); self.leftView.layer.shadowOpacity = 0.8f; self.leftView.layer.shadowRadius = 5.f; // 给 shadowView 添加和 leftview 同样的阴影效果 self.shadowView.layer.shadowOffset = CGSizeMake(5, 5); self.shadowView.layer.shadowOpacity = 0.8f; self.shadowView.layer.shadowRadius = 5.f; // 将view裁剪 self.rightView.layer.masksToBounds = YES; } @end
运行的效果如图:
注意看左边视图的阴影范围,很好的说明了图层的阴影继承自内容的外形,而不是根据边界来界定。
图层阴影并不老是方的,而是从内容的形状继承来的。由于计算阴影是一个很耗资源的步骤,尤为有多个子图层的时候。若是咱们指定阴影的形状的话,能够指定阴影的样子来节省计算阴影的资源开销。shadowPath
就是作这个事的,它是一个CGPathRef
类型(指向CGPath
的指针)。
下图展现了赞成寄宿图不一样阴影的设定:
上图的代码实现:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *layerView1; @property (weak, nonatomic) IBOutlet UIImageView *layerView2; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.layerView1.layer.shadowOpacity = 0.5f; self.layerView2.layer.shadowOpacity = 0.5f; // 添加矩形阴影 CGMutablePathRef squarePath = CGPathCreateMutable(); CGPathAddRect(squarePath, NULL, self.layerView1.bounds); self.layerView1.layer.shadowPath = squarePath; CGPathRelease(squarePath); // 添加圆形阴影 CGMutablePathRef circlePath = CGPathCreateMutable(); CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds); self.layerView2.layer.shadowPath = circlePath; CGPathRelease(circlePath); } @end
若是一个矩形或者圆形,用CGPath
很简单能够实现,若是复杂的图就须要借助UIBezierPath
来实现了。
这节的原文章前有一堆铺垫的,我就不说了,想看的 点击查看原文
本节主要是介绍CALayer
的maskt
属性,它能够实现一些比较好玩的裁剪效果。而不是常规的圆形、矩形裁剪。mask
图层的Color
属性可有可无,它真正有用的是图层的轮廓。以下图所示同样,mask
属性像是一个切割机,mask
图层实心的地方会被保留,其余地方被抛弃。
下面咱们实现如下上图的效果,首先在Storyboard
里建立一个UIImageView
,而后代码以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 建立mask CALayer *maskLayer = [CALayer layer]; maskLayer.frame = self.imageView.bounds; UIImage *maskImage = [UIImage imageNamed:@"test_mask"]; maskLayer.contents = (__bridge id)maskImage.CGImage; // 添加到 imageview 上 self.imageView.layer.mask = maskLayer; // 两张图片素材是在原文中截图处理的,因此展现的效果和原文有所差异。 } @end
运行效果以下:
CALayer
蒙板图层不局限于静态图,也能够经过代码甚至是动画实时生成蒙板。
关于这些我看了原文,确实不懂,并且我也没碰到过,无从下手作笔记。若是想了解的话 请点击此处
UIView
有一个alpha
属性来决定视图的透明度,对应的CALayer
有一个opacity
属性。这两个属性都会影响子层级的显示透明度。
下面作个示例。如今Storyboard
里放置两个UIButton
。而后代码以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIButton *leftBtn; @property (weak, nonatomic) IBOutlet UIButton *rightBtn; @end @implementation ViewController - (UILabel *)subLbl { UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 90, 40)]; label.text = @"Hello World"; label.backgroundColor = [UIColor whiteColor]; label.textAlignment = NSTextAlignmentCenter; return label; } - (void)viewDidLoad { [super viewDidLoad]; [self.leftBtn addSubview:[self subLbl]]; [self.rightBtn addSubview:[self subLbl]]; self.rightBtn.alpha = 0.5; } @end
运行的效果以下:
这显示的效果有点怪。右边的设置了alpha
为0.5
。可是在UILabel
的位置好像不是0.5
的效果。这是由于透明度的混合叠加形成的。实际上右侧中间的透明度是0.75
。
当显示一个50%透明度的图层时,图层的每一个像素都会一半显示本身的颜色,另外一半显示图层下面的颜色。这是正常的透明度的表现。可是若是图层包含一个一样显示50%透明的子图层时,你所看到的视图,50%来自子视图,25%来了图层自己的颜色,另外的25%则来自背景色。
若是想保持透明度一直。咱们能够在info.plist
文件中添加UIViewGroupOpacity
并设置成YES
来打到这个效果。还有一种方法就是对CALayer
进行设置。shouldRasterize
属性能够实现组透明,若是设置成YES
,图层和它的子图层会被合成一个总体图片。
启用shouldRasterize
属性,通常须要同时设置图层的rasterizationScale
属性防止出现Retina屏幕像素化的问题。
shouldRasterize和UIViewGroupOpacity一块儿的时候,会出现性能问题,后面再讲。
对上面的展现效果处理的代码以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIButton *leftBtn; @property (weak, nonatomic) IBOutlet UIButton *rightBtn; @end @implementation ViewController - (UILabel *)subLbl { UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 90, 40)]; label.text = @"Hello World"; label.backgroundColor = [UIColor whiteColor]; label.textAlignment = NSTextAlignmentCenter; return label; } - (void)viewDidLoad { [super viewDidLoad]; [self.leftBtn addSubview:[self subLbl]]; [self.rightBtn addSubview:[self subLbl]]; self.rightBtn.alpha = 0.5; self.rightBtn.layer.rasterizationScale = [UIScreen mainScreen].scale; self.rightBtn.layer.shouldRasterize = YES; } @end
效果如咱们所愿。