Swift - MJRefresh库的使用详解2(创建自定义的下拉刷新组件)
相关文章系列(代码均已升级至Swift4):
如果我们需要实现一个个性化的下拉组件,比如在上面添加些其他组件,或者改变原来的布局。那么可以通过继承 MJRefreshHeader 来实现一个自定义的下拉组件。
1,样例效果图
(1)这个原来是 MJRefresh 提供的一个样例,我这里改成使用 Swift 实现。
(2)下拉组件视图中放置4个控件:上方一个 UIImageView,下方从左到右是 UISwitch、UILabel、UIActivityIndicatorView。
(3)其中文本标签的文字颜色会随着下拉的距离,从红色渐变到蓝色。
(4)“下拉”状态下开关是关闭的,到了“松开刷新”、“正在刷新”这两个状态下开关自动变成打开。(5)UIActivityIndicatorView 活动指示器只有在“正在刷新”状态下会显示出来。




2,自定义组件实现
class MJDIYHeader: MJRefreshHeader { var label:UILabel! var s:UISwitch! var logo:UIImageView! var loading:UIActivityIndicatorView! //在这里做一些初始化配置(比如添加子控件) override func prepare() { super.prepare() // 设置控件的高度 self.mj_h = 50 // 添加label self.label = UILabel() self.label.textColor = UIColor(red:1.0, green:0.5, blue:0.0, alpha:1.0) self.label.font = UIFont.boldSystemFont(ofSize: 16) self.label.textAlignment = .center self.addSubview(self.label) // 打酱油的开关 self.s = UISwitch() self.addSubview(self.s) // logo self.logo = UIImageView(image:UIImage(named:"logo")) self.logo.contentMode = .scaleAspectFit self.addSubview(self.logo) // loading self.loading = UIActivityIndicatorView(activityIndicatorStyle: .gray) self.addSubview(self.loading) } //在这里设置子控件的位置和尺寸 override func placeSubviews() { super.placeSubviews() self.label.frame = self.bounds //self.logo.backgroundColor = UIColor.red self.logo.bounds = CGRect(x:0, y:0, width:self.bounds.size.width, height:50) self.logo.center = CGPoint(x:self.mj_w * 0.5, y:-30) self.loading.center = CGPoint(x:self.mj_w - 30, y:self.mj_h * 0.5) } //监听控件的刷新状态 override var state: MJRefreshState{ didSet { switch (state) { case .idle: self.loading.stopAnimating() self.s.setOn(false, animated: true) self.label.text = "赶紧下拉吖(开关是打酱油滴)" break case .pulling: self.loading.stopAnimating() self.s.setOn(true, animated: true) self.label.text = "赶紧放开我吧(开关是打酱油滴)" break case .refreshing: self.s.setOn(true, animated: true) self.label.text = "加载数据中(开关是打酱油滴)" self.loading.startAnimating() break default: break } } } //监听拖拽比例(控件被拖出来的比例) override var pullingPercent: CGFloat { didSet { // 1.0 0.5 0.0 // 0.5 0.0 0.5 let red = 1.0 - pullingPercent * 0.5 let green = 0.5 - 0.5 * pullingPercent let blue = 0.5 * pullingPercent self.label.textColor = UIColor(red:red, green:green, blue:blue, alpha:1.0) } } //监听scrollView的contentOffset改变 override func scrollViewContentOffsetDidChange(_ change: [AnyHashable : Any]!) { super.scrollViewContentOffsetDidChange(change) } //监听scrollView的contentSize改变 override func scrollViewContentSizeDidChange(_ change: [AnyHashable : Any]!) { super.scrollViewContentSizeDidChange(change) } //监听scrollView的拖拽状态改变 override func scrollViewPanStateDidChange(_ change: [AnyHashable : Any]!) { super.scrollViewPanStateDidChange(change) } }
3,组件使用样例
import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { var items:[String]! var tableView:UITableView? // 顶部刷新 let header = MJDIYHeader() override func loadView() { super.loadView() } override func viewDidLoad() { super.viewDidLoad() //随机生成一些初始化数据 refreshItemData() //创建表视图 self.tableView = UITableView(frame: self.view.frame, style:.plain) self.tableView!.delegate = self self.tableView!.dataSource = self //创建一个重用的单元格 self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "SwiftCell") self.view.addSubview(self.tableView!) //下拉刷新相关设置 header.setRefreshingTarget(self, refreshingAction: #selector(ViewController.headerRefresh)) self.tableView!.mj_header = header } //初始化数据 func refreshItemData() { items = [] for _ in 0...9 { items.append("条目\(Int(arc4random()%100))") } } //顶部下拉刷新 @objc func headerRefresh(){ print("下拉刷新.") sleep(2) //重现生成数据 refreshItemData() //重现加载表格数据 self.tableView!.reloadData() //结束刷新 self.tableView!.mj_header.endRefreshing() } //在本例中,只有一个分区 func numberOfSections(in tableView: UITableView) -> Int { return 1 } //返回表格行数(也就是返回控件数) func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.items.count } //创建各单元显示内容(创建参数indexPath指定的单元) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //为了提供表格显示性能,已创建完成的单元需重复使用 let identify:String = "SwiftCell" //同一形式的单元格重复使用,在声明时已注册 let cell = tableView.dequeueReusableCell(withIdentifier: identify, for: indexPath) cell.accessoryType = .disclosureIndicator cell.textLabel?.text = self.items[indexPath.row] return cell } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }源码下载:

tableView.setContentOffset(CGPoint(x: 0,y: -124),animated: true)
为什么这样子不触发下拉刷新呢?如果我要在底部按钮,按第一次切换,连按两次下拉刷新该怎么做呢?