Swfit - 使用自定义的UIRefreshControl下拉刷新界面
作者:hangge | 2015-11-12 08:50
默认 UIRefreshControl 下拉刷新界面是一个菊花进度条+一段描述文字,略显单调。其实我们可以使用自己创建的界面视图,方便我们实现各种效果。比如添加个动态图片,添加个动画效果什么的。






1,下面演示如何使用自定义的下拉刷新界面,效果图如下:
(1)随着下拉,界面透明度从0开始慢慢显示出来

(2)开始刷新时,文字会有跑马灯效果(字体逐个变大,同时会变色)

2,首先使用xib创建一个界面(RefreshView.xib)
(1)其属性做如下设置

(2)在里面添加6个Label,用来显示描述文字(由于文字要单独播放动画,所以要分开)

(3)分别给各个Label添加约束
我习惯先给中间一个定好位,其它的文本标签根据中间的来排。由于是6个Label,那就先设置第3个Label(“刷”)的约束,宽高固定,垂直居中,水平-19居中。

设置第2个Label(“拉”)约束,宽高固定,水平距右10,垂直居中

其它标签依次类推(间距都是10)
3,主页代码
(1)为更好的看到效果,模拟网络请求,这里使用NSTimer延时3秒生成数据
(2)一定要把 UIRefreshControl 的 backgroundColor 和 tintColor 设置成 UIColor.clearColor()。否则自定义的刷新界面高度不会自动拉伸,会变成固定高度的。
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
//新闻列表
@IBOutlet weak var newsTableView: UITableView!
//新闻数组集合
var dataArray:[HanggeArticle] = [HanggeArticle]()
//拉刷新控制器
var refreshControl = UIRefreshControl()
var customView: UIView!
var labelsArray: Array<UILabel> = []
var currentColorIndex = 0
var currentLabelIndex = 0
var timer: NSTimer!
override func viewDidLoad() {
super.viewDidLoad()
//添加刷新
refreshControl.addTarget(self, action: "refreshData",
forControlEvents: UIControlEvents.ValueChanged)
//背景色和tint颜色都要清除,保证自定义下拉视图高度自适应
refreshControl.backgroundColor = UIColor.clearColor()
refreshControl.tintColor = UIColor.clearColor()
newsTableView.addSubview(refreshControl)
loadData()
//加载自定义刷新界面
loadCustomRefreshView()
}
//自定义刷新界面
func loadCustomRefreshView() {
let refreshContents = NSBundle.mainBundle().loadNibNamed("RefreshView",
owner: self, options: nil)
customView = refreshContents[0] as! UIView
customView.frame = refreshControl.bounds
customView.alpha = 0.0
for var i=0; i<customView.subviews.count; ++i {
labelsArray.append(customView.viewWithTag(i + 1) as! UILabel)
}
refreshControl.addSubview(customView)
}
//滚动视图开始拖动
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
if !refreshControl.refreshing {
self.labelsArray[0].text = "下"
self.labelsArray[1].text = "拉"
self.labelsArray[2].text = "刷"
self.labelsArray[3].text = "新"
self.labelsArray[4].text = "数"
self.labelsArray[5].text = "据"
}
}
//视图拖动
func scrollViewDidScroll(scrollView: UIScrollView) {
//加载界面透明度改变
let sg = ( scrollView.contentOffset.y * -1 ) / 60.0
customView.alpha = sg
}
// 刷新数据
func refreshData() {
self.labelsArray[0].text = "数"
self.labelsArray[1].text = "据"
self.labelsArray[2].text = "加"
self.labelsArray[3].text = "载"
self.labelsArray[4].text = "中"
self.labelsArray[5].text = "..."
//播放动画
playAnimateRefresh()
//模拟加载数据
timer = NSTimer.scheduledTimerWithTimeInterval(3.0, target: self,
selector: "loadData", userInfo: nil, repeats: true)
}
//播放文字动画
func playAnimateRefresh() {
//文字放大,变色动画
UIView.animateWithDuration(0.15, delay: 0.0,
options: .CurveLinear, animations: { () -> Void in
self.labelsArray[self.currentLabelIndex].transform =
CGAffineTransformMakeScale(1.5, 1.5)
self.labelsArray[self.currentLabelIndex].textColor =
self.getNextColor()
}, completion: { (finished) -> Void in
//文字样式还原动画
UIView.animateWithDuration(0.1, delay: 0.0,
options: .CurveLinear, animations: { () -> Void in
self.labelsArray[self.currentLabelIndex].transform =
CGAffineTransformIdentity
self.labelsArray[self.currentLabelIndex].textColor =
UIColor.blackColor()
}, completion: { (finished) -> Void in
++self.currentLabelIndex
if self.currentLabelIndex == self.labelsArray.count - 1 {
self.currentLabelIndex = 0
}
//没加载完则继续播放动画
if self.refreshControl.refreshing {
self.playAnimateRefresh()
}else{
self.currentLabelIndex = 0
}
})
})
}
//计时器时间到,加载数据
func loadData() {
//移除老数据
self.dataArray.removeAll()
//随机添加5条新数据(时间是当前时间)
for _ in 0..<5 {
let atricle = HanggeArticle(title: "新闻标题\(Int(arc4random()%1000))",
createDate: NSDate())
self.dataArray.append(atricle)
}
self.newsTableView.reloadData()
self.refreshControl.endRefreshing()
timer?.invalidate()
timer = nil
}
// 返回记录数
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count;
}
// 返回单元格内容
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle,
reuseIdentifier: "myCell")
//设置单元格标题
let atricle: HanggeArticle = dataArray[indexPath.row] as HanggeArticle
cell.textLabel?.text = atricle.title
//设置单元格副标题
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let str = dateFormatter.stringFromDate(atricle.createDate)
cell.detailTextLabel?.text = str
return cell;
}
//获取下一个颜色
func getNextColor() -> UIColor {
var colorsArray: Array<UIColor> = [UIColor.magentaColor(),
UIColor.brownColor(), UIColor.yellowColor(), UIColor.redColor(),
UIColor.greenColor(), UIColor.blueColor(), UIColor.orangeColor()]
if currentColorIndex == colorsArray.count {
currentColorIndex = 0
}
let returnColor = colorsArray[currentColorIndex]
++currentColorIndex
return returnColor
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
//新闻结构体
struct HanggeArticle {
var title:String
var createDate:NSDate
}
全部评论(4)
博主你好,
refreshControl.addTarget(self, action: "refreshData", forControlEvents: .ValueChanged)
这个绑定的方法是valueChange,现在是向下拉一段距离后就会触发更新,我想实现松开手才进行更新,但是我在绑定方法里面进行了参数修改,尝试无果,望指导
站长回复:你可以不使用ValueChanged事件方法,而是改用在scrollViewDidEndDecelerating方法中触发数据刷新操作(记得刷新前判断下refreshControl.refreshing)
航哥,上拉加载更多怎样做的,个人比较菜,望指导....
站长回复:好的,后面我会写篇上拉加载的文章。按计划,要排到下个月了。
你demo中的文字动画,可以用CA动画替换么?需要注意什么???
站长回复:当然可以,毕竟UIView动画本质上是对CoreAnimation动画的封装。
对于样例中的效果,用UIView动画是因为写起来更简单。如果复杂的效果,UIView动画不好实现的话可以考虑使用CoreAnimation动画。
我按照你的方法,设置了刷新动画customView.frame = refreshControl.bounds;
但是动画宽度,高度固定为320,60,refreshControl.bounds赋给自定义动画钱也是320,60为什么?
站长回复:不管是4s还是6s,初始化的时候宽高确实都是320,60(因为还没显示出来)。但你下拉刷新的时候,refreshControl高度会动态改变,宽度也根据设备的不同而不同(比如6s就是375)。 同样,customView尺寸在下拉时也会改变