模仿微博的刷新,这个刷新的控件是添加到tabelView上的,有时候系统给的刷新控件已经不满足我们的需要了,所以要自定义了
**首先用枚举确定类型,是正常,下拉,还是刷新
/// 枚举确定类型
enum RefreshType:Int {
case Normal = 0
case Pulling = 1
case Refresh = 2
}
**将要移动到控件到父view 上, 使用kvo监听,得到scroll的变化,关键是通过scrollView.contentOffSet.y,通过判断它的改变,判断是哪种状态.
//MARK: - 01.将控件添加到视图
override func willMoveToSuperview(newSuperview: UIView?) {
//判断是否为nil,并且能够滚动
guard let scrollView = newSuperview as?UIScrollView else{
return
}
//kvo监听属性的变化
self.scrollView = scrollView
self.scrollView?.addObserver(self, forKeyPath: "contentOffset", options: NSKeyValueObservingOptions.New, context: nil)
}
//MARK: - 得到scroll 的变化
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
getRefreshStates(self.scrollView!.contentOffset.y)
}
//MARK: - 通过contentOffsetY 判断状态
/*
拖动时候,未松手
- 小于 控件高 + 导航栏高 -->正常状态
- 大于/等于 控件高 + 导航栏高 -->下拉状态
拖动,松手
- 下拉状态,改变刷新状态
*/
func getRefreshStates(contentOffsetY:CGFloat){
let contentInsetTop = self.scrollView?.contentInset.top ?? 0
if contentInsetTop == 0
{
//自己隐藏
self.hidden = true
}else{
self.hidden = false
if self.scrollView!.dragging {//未松手
if contentOffsetY > -contentInsetTop - refreshHeight && wwState == .Pulling{
wwState = .Normal
}else if contentOffsetY <= -contentInsetTop - refreshHeight && wwState == .Normal{
wwState = .Pulling
}
}else {//松手
if wwState == .Pulling{
wwState = .Refresh
}
}
}
}
这里是当它是正常状态下需要判断上一状态,从而做出不同的需求
/// 控件高度
let refreshHeight:CGFloat = 50
class WWRefreshView: UIControl {
//属性 scrollview
var scrollView : UIScrollView?
var wwState:RefreshType = .Normal{
didSet{
switch wwState{
case .Normal:
messageLabel.text = "正常"
UIView.animateWithDuration(0.25) { () -> Void in
self.pullImage.transform = CGAffineTransformIdentity
}
//判断上一个状态是刷新
if oldValue == .Refresh{
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.scrollView?.contentInset.top -= refreshHeight
},completion:{ (_) -> Void in
// 显示箭头
self.pullImage.hidden = false
// 停止动画
self.indicatorView.stopAnimating()
})
}
case .Pulling://下拉
messageLabel.text = "下拉"
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.pullImage.transform = CGAffineTransformMakeRotation(CGFloat(-3*M_PI))
})
case .Refresh:
messageLabel.text = "刷新"
//隐藏箭头,开始转圈
pullImage.hidden = true
indicatorView.startAnimating()
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.scrollView?.contentInset.top += refreshHeight
}, completion: { (_) -> Void in
//外界可以调用
self.sendActionsForControlEvents(UIControlEvents.ValueChanged)
})
}
}
}
** 最后要移除
//移除
deinit{
self.scrollView?.removeObserver(self, forKeyPath: "contentOffset")
}
}