Swift - MJRefresh库的使用详解2(创建自定义的下拉刷新组件)
作者:hangge | 2016-10-25 09:29
相关文章系列(代码均已升级至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()
}
}
源码下载:
全部评论(1)
tableView.setContentOffset(CGPoint(x: 0,y: -124),animated: true)
为什么这样子不触发下拉刷新呢?如果我要在底部按钮,按第一次切换,连按两次下拉刷新该怎么做呢?
站长回复:调用下拉组件的beginRefreshing方法可以触发下拉刷新,比如:header.beginRefreshing()