这个demo制作时,本人水平比较浅显,大家姑且将其当作参考,不必太过纠结其中不合理的地方。本人已经针对swift3作出适配修改,感谢大家的关注。
设计效果如下:
以下是原Idea作者的Dribble:Daily-UI-094-News 地址和本人的GitHub:CBPullToReflesh 地址,希望大家点击支持,再次感谢。
思路分析:
以下将针对设计过程中的知识点进行详细的记录。
使用贝塞尔曲线画波纹
这样的曲线相对简单,我们这里直接使用系统提供的一次贝塞尔曲线方法:
1 |
public func addQuadCurveToPoint(endPoint: CGPoint, controlPoint: CGPoint) |
但是我们还需要根据scrollView的contentOffSet来动态改变该曲线的弧线曲折度,所以这里我们将改变曲折度写成一个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
func wavePath(bendDist bendDist:CGFloat) -> CGPathRef { let width = self.frame.width let height = self.frame.height let bottomLeftPoint = CGPointMake(0, height) let topMidPoint = CGPointMake(width / 2, -bendDist) let bottomRightPoint = CGPointMake(width, height) let bezierPath = UIBezierPath() bezierPath.moveToPoint(bottomLeftPoint) bezierPath.addQuadCurveToPoint(bottomRightPoint, controlPoint: topMidPoint) bezierPath.addLineToPoint(bottomLeftPoint) return bezierPath.CGPath } |
这样我们就可以通过只传入bendDist来改变曲折度。
波纹曲线回滚动画
根据上面的动图,我们可以看到开始刷新操作时,曲折度逐渐减小,这里我们需要一个动画来实现这个功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
func boundAnimation(bendDist bendDist: CGFloat) { let bounce = CAKeyframeAnimation(keyPath: "path") bounce.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) let values = [ self.wavePath(bendDist: bendDist), self.wavePath(bendDist: bendDist * 0.8), self.wavePath(bendDist: bendDist * 0.6), self.wavePath(bendDist: bendDist * 0.4), self.wavePath(bendDist: bendDist * 0.2), self.wavePath(bendDist: 0) ] bounce.values = values bounce.duration = bounceDuration bounce.removedOnCompletion = false bounce.fillMode = kCAFillModeForwards bounce.delegate = self self.waveLayer.addAnimation(bounce, forKey: "return") } |
至此波纹曲线的部分就基本完成。
scrollView回滚动画
问题
在进行波纹曲线回滚动画的时候,我们的scrollView也有适当的上移,这样的上移动画,如果直接使用setContentOffset
来进行视图的移动,选择animation: true
的情况下,每一次移动,都会使得scrollView从顶部重新移动到目标位置,造成视图一直闪的情况。
解决方案
为了避免这样的情况,我们可以依然选择setContentOffset
来进行scrollView的视图移动,但是我们设置animation: false
来关闭系统提供的动画,选择自己来实现动画的效果。
- 首先,我们设置一个定时器:
1 |
NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "scollBackAnimation:", userInfo:stepNum, repeats: true) |
这个定时器的时间步进我们设置为0.01s,是因为NSTimer
准确度并不高。然后我们给这个定时器附加一个stepNum
的属性,这个属性指的是每一次执行setContentOffset
向上移动的距离,这个属性的值,我们这样子计算:
然后,我们每隔0.01秒,刷新一次contentOffset
,形成一种视图向上持续移动的视觉效果,代码如下: