之前项目有一个动态加载进度条的需求,在开发过程中踩了一些坑,今天有时间整理出来,一方面为自己做个记录,另一方面希望同行们遇到相类似的开发需求时能够少踩一些坑
要实现的效果是:动态的加载渐变色进度条
动态加载:需要用到 CABasicAnimation 渐变色:需要用到CAGradientLayer
实现的思路如下图所示
图一图解:
通过贝塞尔曲线绘制想要的曲线,将绘制出的曲线赋值给CAShapLayer 的path属性, 利用CAGradientLayer 呈现渐变色效果,将动画添加到CAShapeLayer上 实现动画加载,这个动态加载主要是通过了CAGradientLayer的Mask属性来实现的
层级结构主要有三层:
最下面一层是CAShaperLayer的背景层 中间一层是CAGradientLayer层 上面一层是CAGradientLayer的Mask属性层,也是CAShaperLayer 然后将动画添加到这个layer上面 整个动画的加载实际上是这个Mask属性在动态变化,从而从视觉上实现渐变色的动态加载,下面具体说道Mask属性 会说到
遇到的问题以及想说的点主要是以下四个方面
一、CABasicAnimation的循环引用
二、图层树
三、CAShapeLayer和CABasicAnimation 属性组合效果
四、CAGradientLayer Mask属性的使用
下面具体说下这四个方面的注意点
一、CABasicAnimation的循环引用
形成条件:
1、实现了动画的代理
2、动画的属性设置为removedOnCompletion = NO;
我们在开发过程中 遇到的代理一般是用weak来修饰的,但动画的这个代理是用strong来修饰的,这在苹果里面是为数不多的情况
图二如果满足了上面的两个条件,就会形成循环引用的情况,如下图所示
图三控制器持有某个视图 视图持有layer layer持有动画 动画持有控制器,完美的形成了一个循环,导致谁都无法释放,造成内存泄漏
解决办法:
在动画执行前,算好视图在动画结束时的位置,并先这个位置赋值给视图。动画的属性设置为removedOnCompletion = YES 即当动画执行完成时,将动画移除掉,动画没有了,就不会持有控制器,控制器也不会持有动画 ,这样链条就被打破了。
二、图层树
Layer也和View一样存在着一个层级树状结构,称之为图层树(Layer Tree),有以下三种:
模型树:直接创建的或者通过UIView获得的(view.layer)用于显示的图层树称之为模型树(Model Tree),模型树的属性在其被修改的时候就变成了新的值,这个是可以用代码直接操控的部分,模型树的背后还存在两份图层树的拷贝,一个是呈现树(Presentation Tree),一个是渲染树(Render Tree)。
呈现树:可以通过普通layer(其实就是模型树)的layer.presentationLayer获得,而模型树则可以通过modelLayer属性获得,呈现树的属性值和动画运行过程中界面上看到的是一致的。
渲染树:渲染树是私有的,你无法访问到,渲染树是对呈现树的数据进行渲染,为了不阻塞主线程,渲染的过程是在单独的进程或线程中进行的,所以你会发现Animation的动画并不会阻塞主线程。
渲染树是CoreAnimation内部的功能,我们基本不会遇到它,而模型树和呈现树却经常会碰到,像我这个项目中需要实时抓取视图在动画过程中 X方向的偏移量,就是通过获取呈现树来抓取的
三、CAShapeLayer和CABasicAnimation 属性组合效果
添加动画时 keyPath有两种:strokeStart、strokeEnd,由于keyPath不同,fromValue 、toValue值的不同 大概会有以下四种效果
strokeStart默认为0, strokeEnd默认为1
一、 keyPath = strokeStart
fromValue = 0,toValue = 1 strokeStart从 0 - 1 ,strokeStart = 0 时有一条完整的路径,strokeStart = 1 时 路径消失。效果:路径起点到终点慢慢的消失
fromValue = 1,toValue = 0 strokeStart从 1 - 0 ,strokeStart = 1 时无路径,strokeStart = 0 时 画出一条完整的路径。效果:路径从终点到起点慢慢的出现
二、keyPath = strokeEnd
fromValue = 0,toValue = 1 ,strokeEnd从 0-1,strokeEnd=0 时,无路径,strokeEnd=1 时,一条完整路径。效果:路径起点到终点慢慢的出现
fromValue = 1,toValue = 0 strokeStart默认为0,strokeEnd从 1-0,strokeEnd=1 时,一条完整路径,strokeEnd=0 时,无路径 效果:路径从终点到起点慢慢消失
四、CAGradientLayer Mask属性的使用
1、当渐变色layer设置了mask后,那么它只会显示与mask重叠部分,相当于masklayer对渐变色layer显示做了截取 实现动态加载进度 实际上是masklayer在不断变化
2、重叠部分的alpha与masklayer的alpha值有关
整个动画加载的本质并不是渐变色在运动,实际上是渐变色在一开始加载时就已经绘制完成了,而是渐变色上面的遮罩层在不断变化,从而造成截取的内容在不断变化,造成的视图效果看着像是渐变色在变化而已。
以上就是在开发时遇到的问题,以及自己感觉比较重要的点。欢迎同行们有问题交流~~
网友评论