博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CBPullToReflesh 一款炫酷的下拉刷新
阅读量:6470 次
发布时间:2019-06-23

本文共 3850 字,大约阅读时间需要 12 分钟。

设计效果如下:

Dribbble网址:

Github网址:

思路分析

以下将针对设计过程中的知识点进行详细的记录。

使用贝塞尔曲线画波纹

这样的曲线相对简单,我们这里直接使用系统提供的一次贝塞尔曲线方法:

public func addQuadCurveToPoint(endPoint: CGPoint, controlPoint: CGPoint)

但是我们还需要根据scrollView的contentOffSet来动态改变该曲线的弧线曲折度,所以这里我们将改变曲折度写成一个方法:

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来改变曲折度。

波纹曲线回滚动画

根据上面的动图,我们可以看到开始刷新操作时,曲折度逐渐减小,这里我们需要一个动画来实现这个功能:

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来关闭系统提供的动画,选择自己来实现动画的效果。

首先,我们设置一个定时器:

NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "scollBackAnimation:", userInfo:stepNum, repeats: true)

这个定时器的时间步进我们设置为0.01s,是因为NSTimer准确度并不高。然后我们给这个定时器附加一个stepNum的属性,这个属性指的是每一次执行setContentOffset向上移动的距离,这个属性的值,我们这样子计算:

然后,我们每隔0.01秒,刷新一次contentOffset,形成一种视图向上持续移动的视觉效果,代码如下:

func scollBackAnimation(timer: NSTimer) {    let stepNum = timer.userInfo! as! CGFloat    scrollViewContentOffSetY = scrollViewContentOffSetY! + stepNum    if scrollViewContentOffSetY >= finalScrollViewContentOffSetY {        timer.invalidate()    }    scrollView?.setContentOffset(CGPoint(x: 0, y: scrollViewContentOffSetY!), animated: false)}

接下来,我们来做小球的部分。

使用贝塞尔曲线画小球

这里,我们使用贝塞尔曲线画任意弧度的一个方法:

public convenience init(arcCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)

这个工厂方法用于画弧,参数说明如下:

  • center:弧线中心点的坐标

  • radius:弧线所在圆的半径

  • startAngle:弧线开始的角度值

  • endAngle:弧线结束的角度值

  • clockwise:是否顺时针画弧线

使用贝塞尔曲线画出小球的运动轨迹

画出小球是比较容易的部分,但是想要画出小球的运行轨迹就稍微有点复杂。

以下我们较为详细的来说明一下:

这一部分,如何去做更重要,牵扯到很多小细节,代码就不贴了,请看Github中的项目文件

草稿思维图

至此,我们知道了弧线所在圆的半径R和该孤的角度Θ。现在,我们只要知道x和y,就可以使用上面提到的来画出所要的弧线。

求x,y

根据这个图片,我们定义一个常量为ballSpace(两球之间的间隔),已知球的半径为ballSize / 2,我们可以列出以下公式:

$$ x = (ballSize + ballSpace) * (1.5 - CGFloat(ballTag)) $$

ballTag为每隔球的序号,从0开始。

$$ y = stopDist / 2 $$

stopDist为scrollView停下,小球开始浮动动画的位置。

小球的浮动动画

小球的浮动只是简单的上下位置的变换,值得注意的是每颗小球开始动画的时间点存在差值,这个差值使得小球有了错位浮动的效果,下面是代码:

func floatUpOrDown() {    let move = CAKeyframeAnimation(keyPath: "position.y")    move.values = [0,1,2,3,4,5,4,3,2,1,0,-1,-2,-3,-4,-5,-4,-3,-2,-1,0]    move.duration = 1    move.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)    move.additive = true    move.fillMode = kCAFillModeForwards    move.removedOnCompletion = false    self.addAnimation(move, forKey: move.keyPath)}
let timeDelay: NSTimeInterval =  Double(layerTag!) * 0.2timer = NSTimer.schedule(delay: timeDelay, repeatInterval: 1, handler: { (timer) -> Void in    self.floatUpOrDown()})

总结

至此,demo中的要点都已经简单说明,希望大家有所收获。

转载地址:http://qkjko.baihongyu.com/

你可能感兴趣的文章
MSSQL数据库跨表和跨数据库查询方法简(转)
查看>>
spring3.0.7中各个jar包的作用总结
查看>>
Windows 10 /win10 上使用GIT慢的问题,或者命令行反应慢的问题
查看>>
梯度下降(Gradient descent)
查看>>
Windows平台分布式架构实践 - 负载均衡
查看>>
Android快速开发常用知识点系列目录
查看>>
最容易理解的对卷积(convolution)的解释
查看>>
《机器学习实战》知识点笔记目录
查看>>
完美解决NC502手工sql的查询引擎排序及合计问题
查看>>
PE文件之资源讲解
查看>>
windows 7/mac编译cocos2d-x-3.2*的android工程报错
查看>>
MYSQL导入导出.sql文件(转)
查看>>
git review报错一例
查看>>
《信息安全系统设计基础》 课程教学
查看>>
Linux平台下使用rman进行oracle数据库迁移
查看>>
全栈工程师学习Linux技术的忠告
查看>>
iOS自定制tabbar与系统的tabbar冲突,造成第一次点击各个item图片更换选中,第二次选中部分item图片不改变...
查看>>
C# Dictionary用法总结
查看>>
SVN服务器使用(二)
查看>>
反射获取内部类以及调用内部类方法
查看>>