自定义下拉刷新
// 代表当前控件的状态
enum SHRefreshControlState: Int {
// 正常
case Normal = 0
// 下拉中
case Pulling = 1
// 刷新中
case Refreshing = 2
}
// 控件的高度
let RefreshControlH: CGFloat = 50
class SHRefreshControl: UIControl {
var scrollView: UIScrollView?
// 记录当前状态
var shState:SHRefreshControlState = .Normal{
didSet{
switch shState {
case .Normal:
messageLabel.text = "正常"
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.pullImageView.transform = CGAffineTransformIdentity
})
// 判断上一个状态为刷新中
if oldValue == .Refreshing {
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.scrollView?.contentInset.top -= RefreshControlH
}, completion: { (_) -> Void in
// 显示箭头
self.pullImageView.hidden = false
// 停止动画
self.indicatorView.stopAnimating()
})
}
case .Pulling:
print("下拉中")
messageLabel.text = "下拉中"
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.pullImageView.transform = CGAffineTransformMakeRotation(CGFloat(-3*M_PI))
})
case .Refreshing:
messageLabel.text = "刷新中"
// 设置动画 增加scrollView 滑动距离
// 隐藏箭头
pullImageView.hidden = true
// 菊花开始动画
indicatorView.startAnimating()
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.scrollView?.contentInset.top += RefreshControlH
}, completion: { (_) -> Void in
// 告知外界可以刷新了
self.sendActionsForControlEvents(UIControlEvents.ValueChanged)
})
}
}
}
override init(frame: CGRect) {
super.init(frame: CGRect(x: 0, y: -RefreshControlH, width: UIScreen.mainScreen().bounds.width, height: RefreshControlH))
setupUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - 供外界调用的方法
func endRefreshing(){
// 01 当前的状态改成正常
// 02 减去50
shState = .Normal
}
// 该控件将要加载到那个父视图
override func willMoveToSuperview(newSuperview: UIView?) {
// 判断他是否为nil 而且是可以滚动的
guard let scrollView = newSuperview as? UIScrollView else{
return
}
// kvo
self.scrollView = scrollView
// 监听scrollView 使用kvo
self.scrollView?.addObserver(self, forKeyPath: "contentOffset", options: NSKeyValueObservingOptions.New, context: nil)
}
// 得到scrollView 的变化
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
getSHRefreshControlState(self.scrollView!.contentOffset.y)
}
/*
- 当用户拖动tableView 而且没有松手
- 当contentOffset.y > -114 显示正常 且当前状态为下拉中
- 当contentOffset.y <= -114 下拉中 且当前的状态为正常
- 当用户拖动tableView 而且松手了
- 如果当前的状态为 下拉中 ---》刷新中
- 如果用户松手了 而且当前的状态为下拉中 才能进入刷新中
*/
// 判断当前刷新控件显示状态
func getSHRefreshControlState(contentOffsetY: CGFloat){
// -64
let contentInsetTop = self.scrollView?.contentInset.top ?? 0
// 代表用户正在拖动
if self.scrollView!.dragging {
if contentOffsetY > -contentInsetTop - RefreshControlH && shState == .Pulling{
shState = .Normal
}else if contentOffsetY <= -contentInsetTop - RefreshControlH && shState == .Normal{
shState = .Pulling
}
}else {
// 代表用户松手了
if shState == .Pulling {
shState = .Refreshing
}
}
}
// MARK: - 设置视图
private func setupUI(){
backgroundColor = UIColor.orangeColor()
// 添加控件
addSubview(messageLabel)
addSubview(pullImageView)
addSubview(indicatorView)
messageLabel.translatesAutoresizingMaskIntoConstraints = false
addConstraint(NSLayoutConstraint(item: messageLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0))
addConstraint(NSLayoutConstraint(item: messageLabel, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
pullImageView.translatesAutoresizingMaskIntoConstraints = false
addConstraint(NSLayoutConstraint(item: pullImageView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: -35))
addConstraint(NSLayoutConstraint(item: pullImageView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
indicatorView.translatesAutoresizingMaskIntoConstraints = false
addConstraint(NSLayoutConstraint(item: indicatorView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: -35))
addConstraint(NSLayoutConstraint(item: indicatorView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
}
// MARK: - 懒加载控件
private lazy var messageLabel: UILabel = {
let lab = UILabel()
lab.text = "正常"
lab.textColor = UIColor.whiteColor()
lab.font = UIFont.systemFontOfSize(14)
return lab
}()
// 箭头
private lazy var pullImageView: UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
// 菊花
private lazy var indicatorView: UIActivityIndicatorView = {
let view = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
return view
}()
deinit{
// 记得移除
self.scrollView?.removeObserver(self, forKeyPath: "contentOffset")
}