首先感谢SnapKit,MJRefresh,NVActivityIndicatorView这三个库的作者
1.新建一个类型SDRefreshHeader继承于MJRefreshHeader
导入MJRefresh,NVActivityIndicatorView,SnapKit
其中NVActivityIndicatorView用来实现柱子伸缩动画
import UIKit
import SnapKit
import MJRefresh
import NVActivityIndicatorView
class SDRefreshHeader: MJRefreshHeader {
}
- 懒加载创建相应的子控件,箭头,文字,动画柱子
/// 箭头图标
private lazy var logoView: UIImageView = {
let logoView = UIImageView()
logoView.image = UIImage(named: "tableview_pull_refresh")
return logoView
}()
/// 文字
private lazy var refreshTextLabel: UILabel = {
let refreshTextLabel = UILabel()
refreshTextLabel.text = "下拉刷新"
refreshTextLabel.textColor = SD_GRAY_TEXT_COLOR
refreshTextLabel.font = UIFont.systemFont(ofSize: 15)
return refreshTextLabel
}()
/// 基准线
private lazy var baseLineView: UIView = {
let baseLineView = UIView()
return baseLineView
}()
///柱子
private lazy var indidcatorView: NVActivityIndicatorView = {
let indidcatorView = NVActivityIndicatorView(frame: CGRect.zero, type: .audioEqualizer, color: .red, padding: 0)
indidcatorView.alpha = 0
return indidcatorView
}()
- 重载prepare函数,添加子控件到刷新header父控件,重载placeSubviews函数,设置布局子控件
///添加子控件
override func prepare() {
super.prepare()
addSubview(logoView)
addSubview(refreshTextLabel)
addSubview(baseLineView)
addSubview(indidcatorView)
}
///子控件布局
override func placeSubviews() {
super.placeSubviews()
self.mj_h = 60
logoView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize(width: 30, height: 30))
make.centerY.equalToSuperview()
make.right.equalTo(baseLineView.snp.left).offset(5)
}
baseLineView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize(width: 1, height: 10))
make.centerX.equalToSuperview().offset(-10)
make.centerY.equalToSuperview()
}
refreshTextLabel.snp.makeConstraints { (make) in
make.centerY.equalToSuperview()
make.left.equalTo(baseLineView.snp.right).offset(0)
}
indidcatorView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize(width: 16, height: 16 ))
make.centerY.equalToSuperview()
make.right.equalTo(baseLineView.snp.left).offset(-5)
}
}
- 重载state属性 Set 方法,设置不同刷新状态时的文字,柱子动画显示与隐藏
var oldState: MJRefreshState = .idle
override var state: MJRefreshState {
willSet {
oldState = self.state
if newValue == oldState {return}
}
didSet {
switch self.state {
/// 普通闲置状态
case .idle:
refreshTextLabel.text = "下拉刷新"
if oldState == .refreshing {
self.logoView.transform = CGAffineTransform.identity
UIView.animate(withDuration: 0.25, animations: {
self.indidcatorView.alpha = 0
}) { (finiseed) in
// 如果执行完动画发现不是idle状态,就直接返回,进入其他状态
if self.state != .idle {return}
self.indidcatorView.alpha = 1
self.indidcatorView.stopAnimating()
self.logoView.isHidden = false
}
}else {
logoView.isHidden = false
/// 还原
UIView.animate(withDuration: 0.25) {
self.logoView.transform = CGAffineTransform.identity
}
indidcatorView.alpha = 0
indidcatorView.stopAnimating()
}
break
/// 松开刷新
case .pulling:
refreshTextLabel.text = "松开刷新"
logoView.isHidden = false
UIView.animate(withDuration: 0.25) {
/// 0.000001 - .pi 逆时针旋转 -.pi 顺时针旋转
self.logoView.transform = CGAffineTransform(rotationAngle: CGFloat(0.000001 - .pi))
//CGAffineTransform(rotationAngle: CGFloat(-Double.pi))
}
indidcatorView.alpha = 0
indidcatorView.stopAnimating()
break
/// 刷新中
case .refreshing:
refreshTextLabel.text = "刷新中..."
logoView.isHidden = true
indidcatorView.alpha = 1
indidcatorView.startAnimating()
break
default:
break
}
}
}
Gif效果图如下