Swift开发-实现类似网易云下拉刷新效果

1,702 阅读1分钟

首先感谢SnapKit,MJRefresh,NVActivityIndicatorView这三个库的作者

1.新建一个类型SDRefreshHeader继承于MJRefreshHeader
导入MJRefresh,NVActivityIndicatorView,SnapKit 其中NVActivityIndicatorView用来实现柱子伸缩动画

import UIKit
import SnapKit
import MJRefresh
import NVActivityIndicatorView
class SDRefreshHeader: MJRefreshHeader {

}
  1. 懒加载创建相应的子控件,箭头,文字,动画柱子

    /// 箭头图标
    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
    }()
    
  1. 重载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)
        }
    }
 
 
  1. 重载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效果图如下