用Swift实现淘宝和大众点评的下拉刷新
2016-07-15 16:28
603 查看
来自Leo的原创博客,转载请著名出处
我的StackOverflow
我的Github
https://github.com/LeoMobileDeveloper
大众点评
大众点评的下拉刷新用了50行左右代码
淘宝的下拉刷新用了90行左右代码
完整的代码地址:PullToRefreshKit
Tips:用Swift 2.2写的,所以需要XCode 7.3来运行。
比如,用一行代码实现默认的下拉刷新
效果
不过,这个库的主要目的还是希望大家能方便的实现自定义刷新界面,不管是哪个方向的。
通过它来自定义刷新界面,只需要实现三个协议中的一个。
比如,实现自定义下拉刷新,只需写一个UIView的子类,要遵循协议RefreshableHeader。这个UIView的子类,你可以用AutoLayout,任何你想要使用的布局效果。
这个协议有如下几个方法
下拉的过程中,根据下拉程度,动态调整显示的图片
刷新的时候,显示动图
首先,我们准备好图片,本文的图片来自于MJ哥的MJRefresh
其中,下拉的过程的图片,一共有60张,刷新的时候,动图有3张。
这60张图是不一样的,比如第一张,第1,30,60张如下,下拉的过程就是不断的切换图片
至于刷新的过程中,就是用Imageview,动态播放以下三张图片罢了
所以,代码如下
然后,这样调用
整个下拉刷新的界面如下
其中
是CAShapeLayer,随着滑动,动态调整绘制过程,刷新的时候转圈圈
是CAShapeLayer,静态的,当刷新的时候隐藏
简单的UILabel
在刷新界面上面还有一个Imageview,创建一个Imageview放置到上面即可
所以,完整的代码如下
然后这样使用
Tips:注意到,TaoBaoRefreshHeader的frame的高度是100,但是distanceToRefresh()却返回60,从而实现了顶部的ImageViwe在刷新的时候隐藏
我的StackOverflow
我的Github
https://github.com/LeoMobileDeveloper
效果
淘宝大众点评
项目地址
其中大众点评的下拉刷新用了50行左右代码
淘宝的下拉刷新用了90行左右代码
完整的代码地址:PullToRefreshKit
Tips:用Swift 2.2写的,所以需要XCode 7.3来运行。
PullToRefreshKit
这是我用纯Swift 2.2写的一个库,初衷是为了更简单的实现自定义下拉刷新。当然,它也支持一代码实现:上拉加载,左/右滑动加载更多的操作。比如,用一行代码实现默认的下拉刷新
self.tableView.setUpHeaderRefresh { [weak self] in delay(1.5, closure: { self?.tableView.endHeaderRefreshing(.Success) }) }
效果
不过,这个库的主要目的还是希望大家能方便的实现自定义刷新界面,不管是哪个方向的。
通过它来自定义刷新界面,只需要实现三个协议中的一个。
比如,实现自定义下拉刷新,只需写一个UIView的子类,要遵循协议RefreshableHeader。这个UIView的子类,你可以用AutoLayout,任何你想要使用的布局效果。
这个协议有如下几个方法
//拖拽的触发刷新的距离,也是Header的高度 func distanceToRefresh()->CGFloat //拖拽或者释放的时候,比例的变化。比如总高度是100,当拖拽为10的时候,比例就是0.1,在这里,可以根据百分比动态的设置Header的状态 func percentUpdateWhenNotRefreshing(percent:CGFloat) //松手即将进入刷新状态的回调,在这里,把视图切换为动画状态 func releaseWithRefreshingState() //刷新结束,将要开始隐藏Header的动画,在这里告诉用户刷新失败或者成功 func didBeginEndRefershingAnimation(result:RefreshResult) //刷新结束,Header完全隐藏的回调,这里把Header恢复到最初的状态 func didCompleteEndRefershingAnimation(result:RefreshResult)
大众点评下拉刷新
分析一下,大众点评的下拉刷新主要分为两个状态下拉的过程中,根据下拉程度,动态调整显示的图片
刷新的时候,显示动图
首先,我们准备好图片,本文的图片来自于MJ哥的MJRefresh
其中,下拉的过程的图片,一共有60张,刷新的时候,动图有3张。
这60张图是不一样的,比如第一张,第1,30,60张如下,下拉的过程就是不断的切换图片
至于刷新的过程中,就是用Imageview,动态播放以下三张图片罢了
所以,代码如下
class DianpingRefreshHeader:UIView,RefreshableHeader{ let imageView = UIImageView() //放置Imageview override init(frame: CGRect) { super.init(frame: frame) imageView.frame = CGRectMake(0, 0, 60, 60) imageView.center = CGPointMake(CGRectGetWidth(self.bounds)/2.0, CGRectGetHeight(self.bounds)/2.0 + 10) addSubview(imageView) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } // MARK: - RefreshableHeader - //一共的距离是70 func distanceToRefresh()->CGFloat{ return 60 } //监听百分比变化,切换图片 func percentUpdateWhenNotRefreshing(percent:CGFloat){ imageView.hidden = (percent == 0) let adjustPercent = max(min(1.0, percent),0.0) let scale = 0.2 + (1.0 - 0.2) * adjustPercent; imageView.transform = CGAffineTransformMakeScale(scale, scale) let mappedIndex = Int(adjustPercent * 60) let imageName = "dropdown_anim__000\(mappedIndex)" let image = UIImage(named: imageName) imageView.image = image } //松手即将刷新,播放动图 func releaseWithRefreshingState(){ let images = ["dropdown_loading_01","dropdown_loading_02","dropdown_loading_03"].map { (name) -> UIImage in return UIImage(named:name)! } imageView.animationImages = images imageView.animationDuration = 0.6 imageView.startAnimating() } //刷新结束,将要隐藏header,不做任何处理 func didBeginEndRefershingAnimation(result:RefreshResult){ } //刷新结束,完全隐藏header,恢复到最初状态 func didCompleteEndRefershingAnimation(result:RefreshResult){ imageView.animationImages = nil imageView.stopAnimating() imageView.hidden = true } }
然后,这样调用
let dianpingHeader = DianpingRefreshHeader(frame: CGRectMake(0,0,CGRectGetWidth(self.view.bounds),60)) self.tableView.setUpHeaderRefresh(taobaoHeader) { [weak self] in delay(1.5, closure: { self?.tableView.endHeaderRefreshing(.Success) }) }
淘宝下拉刷新
首先分析视图架构整个下拉刷新的界面如下
其中
是CAShapeLayer,随着滑动,动态调整绘制过程,刷新的时候转圈圈
是CAShapeLayer,静态的,当刷新的时候隐藏
简单的UILabel
在刷新界面上面还有一个Imageview,创建一个Imageview放置到上面即可
所以,完整的代码如下
class TaoBaoRefreshHeader:UIView,RefreshableHeader{ private let circleLayer = CAShapeLayer() private let arrowLayer = CAShapeLayer() private let textLabel = UILabel() private let strokeColor = UIColor(red: 135.0/255.0, green: 136.0/255.0, blue: 137.0/255.0, alpha: 1.0) override init(frame: CGRect) { super.init(frame: frame) setUpCircleLayer() setUpArrowLayer() textLabel.frame = CGRectMake(CGRectGetWidth(self.bounds)/2 - 30, CGRectGetHeight(self.bounds)/2 - 20,120, 40) textLabel.textAlignment = .Center textLabel.textColor = UIColor.lightGrayColor() textLabel.font = UIFont.systemFontOfSize(14) textLabel.text = "下拉即可刷新..." self.addSubview(textLabel) let imageView = UIImageView(frame: CGRectMake(0, 0, 230, 35)) imageView.image = UIImage(named: "taobaoLogo") self.addSubview(imageView) self.addSubview(textLabel) } //绘制中间箭头 func setUpArrowLayer(){ //略去 } //绘制外部圆圈 func setUpCircleLayer(){ //略去 } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } // MARK: - RefreshableHeader - func distanceToRefresh()->CGFloat{ return 60 } //根据滑动百分比,动态调整storkeEnd和文字 func percentUpdateWhenNotRefreshing(percent:CGFloat){ let adjustPercent = max(min(1.0, percent),0.0) self.circleLayer.strokeEnd = 0.05 + (0.95 - 0.05) * adjustPercent if adjustPercent == 1.0{ textLabel.text = "释放即可刷新..." }else{ textLabel.text = "下拉即可刷新..." } } //进入刷新状态,调整圈圈的strokeEnd,为圈圈增加旋转动画,更新label文字 func releaseWithRefreshingState(){ self.circleLayer.strokeEnd = 0.95 let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.z") rotateAnimation.toValue = NSNumber(double: M_PI * 2.0) rotateAnimation.duration = 0.6 rotateAnimation.cumulative = true rotateAnimation.repeatCount = 10000000 self.circleLayer.addAnimation(rotateAnimation, forKey: "rotate") self.arrowLayer.hidden = true textLabel.text = "刷新中..." } //结束刷新的动画开始,停止动画 func didBeginEndRefershingAnimation(result:RefreshResult){ self.circleLayer.removeAllAnimations() } //Header完全隐藏,恢复到原始状态 func didCompleteEndRefershingAnimation(result:RefreshResult){ self.circleLayer.strokeEnd = 0.05 self.arrowLayer.hidden = false textLabel.text = "下拉即可刷新"
然后这样使用
let taobaoHeader = TaoBaoRefreshHeader(frame: CGRectMake(0,0,CGRectGetWidth(self.view.bounds),100)) self.tableView.setUpHeaderRefresh(taobaoHeader) { [weak self] in delay(1.5, closure: { self?.models = (self?.models.map({_ in random100()}))! self?.tableView.endHeaderRefreshing(.Success) }) }
Tips:注意到,TaoBaoRefreshHeader的frame的高度是100,但是distanceToRefresh()却返回60,从而实现了顶部的ImageViwe在刷新的时候隐藏
最后
如果你喜欢这个库,欢迎和我一起把它完善,PullToRefreshKit ,欢迎各种建议,Star,fork。相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- Apple Swift学习教程
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 介绍 Fedora 上的 Swift
- 过滤淘宝网弹出窗口
- js中flexible.js实现淘宝弹性布局方案
- javascript实现的淘宝旅行通用日历组件用法实例
- 基于jQuery仿淘宝产品图片放大镜代码分享
- jQuery实现类似淘宝网图片放大效果的方法
- JS仿淘宝实现的简单滑动门效果代码
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- js判断客户端是iOS还是Android等移动终端的方法
- iOS应用开发中AFNetworking库的常用HTTP操作方法小结