Swift - MJRefresh库的使用详解4(创建自定义的上拉加载组件)
作者:hangge | 2016-10-28 08:50
相关文章系列(代码均已升级至Swift4):
但如果我们需要实现一个个性化的上拉组件,比如在上面添加些其他组件,或者改变原来的布局。那么可以通过继承 MJRefreshAutoFooter 或者 MJRefreshBackFooter 来实现一个自定义的上拉组件。
一、继承MJRefreshAutoFooter
这个实现的是普通自动刷新上拉加载组件,也就是说上拉组件会占用 tableView 的一个单元格。1,样例效果图
(1)这个原来是 MJRefresh 提供的一个样例,我这里改成使用 Swift 实现。
(4)UIActivityIndicatorView 活动指示器只有在“正在刷新”状态下会显示出来。

2,自定义组件实现
3,组件使用样例
hangge_1406.zip



2,自定义组件实现
3,组件使用样例
hangge_1406.zip
(1)这个原来是 MJRefresh 提供的一个样例,我这里改成使用 Swift 实现。
(2)上拉组件视图中放置3个控件:UIActivityIndicatorView、UILabel、UISwitch。
(3)通常状态下开关是关闭的,到了“正在刷新”状态下开关会自动变成打开状态。(4)UIActivityIndicatorView 活动指示器只有在“正在刷新”状态下会显示出来。


class MJDIYAutoFooter: MJRefreshAutoFooter
{
var label:UILabel!
var s:UISwitch!
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)
// loading
self.loading = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.addSubview(self.loading)
}
//在这里设置子控件的位置和尺寸
override func placeSubviews()
{
super.placeSubviews()
self.label.frame = self.bounds
self.s.center = CGPoint(x:self.mj_w - 20, y:self.mj_h - 20)
self.loading.center = CGPoint(x:30, y:self.mj_h * 0.5)
}
//监听控件的刷新状态
override var state: MJRefreshState{
didSet
{
switch (state) {
case .idle:
self.label.text = "赶紧上拉吖(开关是打酱油滴)"
self.loading.stopAnimating()
self.s.setOn(false, animated:true)
break
case .refreshing:
self.s.setOn(true, animated:true)
self.label.text = "加载数据中(开关是打酱油滴)"
self.loading.startAnimating()
break
case .noMoreData:
self.label.text = "木有数据了(开关是打酱油滴)"
self.s.setOn(false, animated:true)
self.loading.stopAnimating()
break
default:
break
}
}
}
//监听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 footer = MJDIYAutoFooter()
override func loadView() {
super.loadView()
}
override func viewDidLoad() {
super.viewDidLoad()
//随机生成一些初始化数据
loadItemData()
//创建表视图
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!)
//上刷新相关设置
footer.setRefreshingTarget(self, refreshingAction: #selector(ViewController.footerLoad))
//是否自动加载(默认为true,即表格滑到底部就自动加载)
footer.isAutomaticallyRefresh = false
self.tableView!.mj_footer = footer
}
//初始化数据
func loadItemData() {
for _ in 0...20 {
items.append("条目\(Int(arc4random()%100))")
}
}
//底部上拉加载
@objc func footerLoad(){
print("上拉加载.")
sleep(2)
//生成并添加数据
loadItemData()
//重现加载表格数据
self.tableView!.reloadData()
//结束刷新
self.tableView!.mj_footer.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()
}
}
源码下载:二、继承MJRefreshBackFooter
这个实现的是自动回弹上拉加载组件,也就是说上拉组件不会占用 tableView 单元格空间。
1,样例效果图
(1)这个原来也是 MJRefresh 提供的一个样例,我这里改成使用 Swift 实现。
(2)下拉组件视图中放置4个控件:最下方一个 UIImageView,上方从左到右是 UISwitch、UILabel、UIActivityIndicatorView。
(3)其中文本标签的文字颜色会随着上拉的距离,从红色渐变到蓝色。
(4)“上拉”状态下开关是关闭的,到了“松开加载”、“正在加载”这两个状态下开关会自动变成打开状态。
(5)UIActivityIndicatorView 活动指示器只有在“正在加载”状态下会显示出来。



2,自定义组件实现
class MJDIYBackFooter: MJRefreshBackFooter
{
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.bounds = CGRect(x:0, y:0, width:self.bounds.size.width, height:50)
self.logo.center = CGPoint(x:self.mj_w * 0.5, y:self.mj_h + self.logo.mj_h * 0.5)
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.loading.startAnimating()
self.s.setOn(true, animated:true)
self.label.text = "加载数据中(开关是打酱油滴)"
break
case .noMoreData:
self.loading.stopAnimating()
self.label.text = "木有数据了(开关是打酱油滴)"
self.s.setOn(false, animated:true)
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 footer = MJDIYBackFooter()
override func loadView() {
super.loadView()
}
override func viewDidLoad() {
super.viewDidLoad()
//随机生成一些初始化数据
loadItemData()
//创建表视图
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!)
//上刷新相关设置
footer.setRefreshingTarget(self, refreshingAction: #selector(ViewController.footerLoad))
self.tableView!.mj_footer = footer
}
//初始化数据
func loadItemData() {
for _ in 0...20 {
items.append("条目\(Int(arc4random()%100))")
}
}
//底部上拉加载
@objc func footerLoad(){
print("上拉加载.")
sleep(2)
//生成并添加数据
loadItemData()
//重现加载表格数据
self.tableView!.reloadData()
//结束刷新
self.tableView!.mj_footer.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()
}
}
源码下载:
全部评论(0)