效果:
<br />
<br />
1、UI布局
<br />
2、代码实现,为了Controller
中的代码不那么臃肿,我们稍微封装一下代码
2.1 封装dataSource
- 1 新建一个类,继承
NSobject
- 2 导入
UITableViewDatasource
- 3 实现代理方法
- 4 封装一个对外公开的类方法:此时应该至少需要Identifier、数据源、有没有Section、回调(闭包)
- 5 提供一个结构体
- 6 提供一个获取数据(模型)的方法
代码如下
//
// TBDataSource.swift
// CustomPullToRefresh
//
// Created by ios on 16/9/26.
// Copyright © 2016年 ios. All rights reserved.
//
import UIKit
/**
设置Section样式,默认 Single
*/
public enum TBSectionStyle : Int {
///Default 默认没有多个Section
case Section_Single
/// 有多个Section
case Section_Has
}
class TBDataSource: NSObject,UITableViewDataSource {
private var sectionStyle : TBSectionStyle = .Section_Single
private var data : NSArray?
private var identifier : String = "null"
private var cellBlock : ((cell : AnyObject, item : AnyObject) -> ())?
/**
快速创建一个数据源,需要提前注册,数组和style要对应
- parameter identifier: 标识
- parameter data: 数据
- parameter style: 类型
- parameter cell: 回调
- returns: 数据源对象(dataSource)
*/
static func cellIdentifierWith(identifier : String , data : NSArray , style : TBSectionStyle , cell : ((cell : AnyObject, item : AnyObject) -> Void)) -> TBDataSource {
let source = TBDataSource()
source.sectionStyle = style
source.data = data
source.identifier = identifier
source.cellBlock = cell
return source
}
/**
返回数据
- parameter indexPath: indexPath
- returns: 数据
*/
private func itemWithIndexPath(indexPath : NSIndexPath) -> AnyObject{
if sectionStyle == .Section_Single {
return data![indexPath.row]
}
else{
return data![indexPath.section][indexPath.row]
}
}
/**
返回有多少个Section
- parameter tableView: tableView
- returns: section
*/
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if sectionStyle == .Section_Single {
return 1
}
return (data?.count)!
}
/**
返回对应Section的rows
- parameter tableView: tableView
- parameter section: section
- returns: rows
*/
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
if sectionStyle == .Section_Single {
return (data?.count)!
}else{
return (data?[section].count)!
}
}
/**
返回cell,并用闭包把cell封装到外面,提供样式设置
- parameter tableView: tableView
- parameter indexPath: indexPath
- returns: cell
*/
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)
if let block = cellBlock {
block(cell: cell, item: itemWithIndexPath(indexPath))
}
return cell
}
}
<br />
封装好DataSource之后,ViewController中声明一个属性,此时对cell外观操作,都在这里处理
/// 数据源
private lazy var dataSource : TBDataSource = {
let source = TBDataSource.cellIdentifierWith("iconCell", data: [["😂", "🤗", "😳", "😌", "😊"],["😂", "🤗", "😳", "😌", "😊"],["😂", "🤗", "😳", "😌", "😊"]], style: TBSectionStyle.Section_Has, cell: { (cell: AnyObject, item: AnyObject) -> () in
let newCell = cell as! UITableViewCell
let newItem = item as! String
newCell.textLabel!.text = newItem
newCell.textLabel?.font = UIFont(name: "Apple Color Emoji", size: 40)
newCell.textLabel?.textAlignment = NSTextAlignment.Center
})
return source
}()
<br />
声明属性之后,只需要执行下面的一行代码便可以展示出数据源了
tableView.dataSource = dataSource
3、封装动画
- 创建一个xib
- 创建一个类,继承
UIRefreshControl
- 提供一个加载xib的类方法
- 在类方法中把xib加载进来的views存入数组,便于做动画
- 实现动画,这里使用
transfrom
,你们也可以自定义其他的动画
代码试下如下:
//
// CustomRefreshView.swift
// CustomPullToRefresh
//
// Created by ios on 16/9/26.
// Copyright © 2016年 ios. All rights reserved.
//
import UIKit
/// 自定义刷新控件
class CustomRefreshView: UIRefreshControl {
private var xibViews : Array<UIView> = []
private var isAnimating : Bool = false
private var currentColorIndex = 0
private var currentLabelIndex = 0
static func addViewsForNib( name : String) -> CustomRefreshView{
let content = NSBundle.mainBundle().loadNibNamed(name, owner: self, options: nil).first as! UIView
let cus = CustomRefreshView()
cus.addSubview(content)
for i in 0..<content.subviews.count {
cus.xibViews.append(content.subviews[i])
cus.xibViews[i].layer.cornerRadius = (cus.xibViews[i].bounds.width + cus.xibViews[i].bounds.height) * 0.25
cus.xibViews[i].clipsToBounds = true
}
return cus
}
/**
向外面提供一个开始动画的方法
*/
func startAnimation(){
animateRefreshStep1()
}
///动画设置 外面不需要知道,所以都设置成为私有方法
private func animateRefreshStep1() {
isAnimating = true
UIView.animateWithDuration(0.1, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in
self.xibViews[self.currentLabelIndex].transform = CGAffineTransformMakeRotation(CGFloat(M_PI_4))
self.xibViews[self.currentLabelIndex].backgroundColor = self.getNextColor()
}, completion: { (finished) -> Void in
UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in
self.xibViews[self.currentLabelIndex].transform = CGAffineTransformIdentity
}, completion: { (finished) -> Void in
self.currentLabelIndex += 1
if self.currentLabelIndex < self.xibViews.count {
self.animateRefreshStep1()
}
else {
self.animateRefreshStep2()
}
})
})
}
///动画设置 外面不需要知道,所以都设置成为私有方法
private func animateRefreshStep2() {
UIView.animateWithDuration(0.40, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in
self.xibViews[0].transform = CGAffineTransformMakeScale(1.5, 1.5)
self.xibViews[1].transform = CGAffineTransformMakeScale(1.5, 1.5)
self.xibViews[2].transform = CGAffineTransformMakeScale(1.5, 1.5)
self.xibViews[3].transform = CGAffineTransformMakeScale(1.5, 1.5)
self.xibViews[4].transform = CGAffineTransformMakeScale(1.5, 1.5)
self.xibViews[5].transform = CGAffineTransformMakeScale(1.5, 1.5)
self.xibViews[6].transform = CGAffineTransformMakeScale(1.5, 1.5)
self.xibViews[7].transform = CGAffineTransformMakeScale(1.5, 1.5)
}, completion: { (finished) -> Void in
UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in
self.xibViews[0].transform = CGAffineTransformIdentity
self.xibViews[1].transform = CGAffineTransformIdentity
self.xibViews[2].transform = CGAffineTransformIdentity
self.xibViews[3].transform = CGAffineTransformIdentity
self.xibViews[4].transform = CGAffineTransformIdentity
self.xibViews[5].transform = CGAffineTransformIdentity
self.xibViews[6].transform = CGAffineTransformIdentity
self.xibViews[7].transform = CGAffineTransformIdentity
}, completion: { (finished) -> Void in
if self.refreshing {
self.currentLabelIndex = 0
self.animateRefreshStep1()
}
else {
self.isAnimating = false
self.currentLabelIndex = 0
for i in 0 ..< self.xibViews.count {
self.xibViews[i].transform = CGAffineTransformIdentity
self.xibViews[i].backgroundColor = UIColor.clearColor()
}
}
})
})
}
///动画设置 外面不需要知道,所以都设置成为私有方法
private 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 += 1
return returnColor
}
}
<br />
完成对动画的封装之后,Controller中的代码如下
//
// ViewController.swift
// CustomPullToRefresh
//
// Created by ios on 16/9/26.
// Copyright © 2016年 ios. All rights reserved.
//
import UIKit
class ViewController: UIViewController ,UITableViewDelegate{
@IBOutlet weak var tableView: UITableView!
/// 数据源
private lazy var dataSource : TBDataSource = {
let source = TBDataSource.cellIdentifierWith("iconCell", data: [["😂", "🤗", "😳", "😌", "😊"],["😂", "🤗", "😳", "😌", "😊"],["😂", "🤗", "😳", "😌", "😊"]], style: TBSectionStyle.Section_Has, cell: { (cell: AnyObject, item: AnyObject) -> () in
let newCell = cell as! UITableViewCell
let newItem = item as! String
newCell.textLabel!.text = newItem
newCell.textLabel?.font = UIFont(name: "Apple Color Emoji", size: 40)
newCell.textLabel?.textAlignment = NSTextAlignment.Center
})
return source
}()
private lazy var refreshControl : CustomRefreshView = CustomRefreshView.addViewsForNib("RefreshContents")
private var isAnimating : Bool = false
var timer: NSTimer!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = dataSource
tableView.delegate = self
tableView.rowHeight = 60
tableView.addSubview(refreshControl)
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
if refreshControl.refreshing {
if !isAnimating {
doSomething()
refreshControl.startAnimation()
}
}
}
/**
开启定时器
*/
private func doSomething() {
timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: #selector(ViewController.endedOfWork), userInfo: nil, repeats: true)
}
/**
定时器结束,关闭动画
*/
@objc private func endedOfWork() {
refreshControl.endRefreshing()
timer.invalidate()
timer = nil
}
}
本文Demo