iOS开发之______MJRefresh

来源:http://www.chinese-glasses.com 作者:Web前端 人气:117 发布时间:2020-04-07
摘要:时间: 2019-10-12阅读: 65标签: 刷新背景 使用过很多下拉刷新,上拉加载的插件,虽然也知道一点原理,但似乎一直不太完全能理解它,闲来无事,手写一个,感受下,借鉴了better-scroll的

时间: 2019-10-12阅读: 65标签: 刷新背景

图片 1

使用过很多下拉刷新,上拉加载的插件,虽然也知道一点原理,但似乎一直不太完全能理解它,闲来无事,手写一个,感受下,借鉴了better-scroll的源码,功能当然相差甚远,也只是个简易版的实现,大概就这意思。

(logo)

!DOCTYPE htmlhtml lang="en"head meta charset="UTF-8" meta name="viewport" content="width=device-width, initial-scale=1.0" meta http-equiv="X-UA-Compatible" content="ie=edge" titleDocument/title style html,body,ul,li,div,input{ padding: 0; margin: 0; } #header { background: red; } #input{ display: inline-block; width: 80%; height: 30px; } #submit { display: inline-block; width: 16%; height: 30px; } #article { position: relative; height: calc(100vh - 34px); overflow:scroll; } #list { position: relative; list-style: none; width: 100%; top: 0px; } /* 刷新 */ #refresh { position: absolute; top: -50px; left: 0; width: 100%; height: 50px; overflow: hidden; color: #969799; font-size: 14px; line-height: 50px; text-align: center; } #text { border: none; line-height: 30px; height: 30px; text-align: center; } .li{ display: flex; justify-content: center; line-height: 80px; height:80px; border-bottom: 1px solid #999; } .load-icon{ height: 50px; line-height: 50px; text-align: center; background: #f0f3f6; } #loading { display: none; } /style/headbody div  header  input type="text"  input type="submit"  /header article  div  div  span 下拉即可刷新.../span /div ul  li 1/li li 2/li li 3/li li 4/li li 5/li li 6/li li 7/li li 8/li li 9/li li 10/li /ul div  span 加载更多/span /div /div /article /div script let article = document.getElementById('article'), // 获取包裹ul列表的div list = document.getElementById("list"), // 列表 loadingDom = document.getElementById("loading"), // 加载dom loadingText = loadingDom.querySelector('.text'), // 写着“加载更多”的元素 // 下拉刷新变量 refreshDom = document.getElementById("refresh"), // 刷新dom refreshText = refreshDom.querySelector('.text'), // 写着“下拉刷新”的元素 start = null, // 辅助变量:触摸开始时,相对于文档顶部的Y坐标 refresh = false; // 辅助变量:是否刷新 let num = 11; // 要添加的li文本,可自定义 let finish = false; // 是否继续加载 let loading = false; // 是否正在加载 // 追加li的方法,可自定义 function addLi() { let fragment = document.createDocumentFragment(); loading = true; for(let i=0;i10;i++) { let li = document.createElement('li'); li.className = 'li'; li.innerHTML = num++; fragment.appendChild(li); // 用DocumentFragment提高渲染速度 } setTimeout(function(){ ul.appendChild(fragment); finish = true; // 设置加载到最低了 loadingText.innerHTML = "已经到底了~"; loading = false },2000) } // 拷贝数组 var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i  arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; // 事件注册 function eventMixin(BScroll) { // 注册事件 BScroll.prototype.on = function (type, fn) { var context = arguments.length  2  arguments[2] !== undefined ? arguments[2] : this; if (!this._events[type]) { this._events[type] = []; } this._events[type].push([fn, context]); }; // 销毁事件 BScroll.prototype.off = function (type, fn) { var _events = this._events[type]; if (!_events) { return; } var count = _events.length; while (count--) { if (_events[count][0] === fn) { _events[count][0] = undefined; } } }; } /** * new Bscroll(this.$refs.wrapper, {}) * 参数1:滚动外层dom * 参数2:配置条件 */ function BScroll(dom,{}){ let that = this; this._events = {}; // init private custom events this.x = 0; // 水平轴移动距离(水平功能暂不考虑,目前只玩y轴) this.y = 0; // 纵轴移动距离 //获取元素滚动条卷曲的高度 this.getScrollTop = function(ele) { return ele.scrollTop || 0; } //获取当前可视范围的高度 this.getClientHeight = function(ele) { return ele.clientHeight || 0; } //获取文档完整的高度 this.getScrollHeight = function(ele){ return ele.clientHeight || 0; } // 触发touchmove事件 this.touchmoveHandle = function(){ this.trigger('touchmove',{ x: this.x, y: this.y }) } // 触发touchend事件 this.touchendHandle = function(){ this.trigger('touchend',{ x: this.x, y: this.y }) } // 滑动开始 article.addEventListener('touchstart',function(event){ let touch = event.touches[0]; start = touch.pageY; // 辅助变量:触摸开始时,相对于文档顶部的Y坐标 },false); // 监听滑动事件 article.addEventListener('touchmove',function(event){ // 下拉刷新 let touch = event.touches[0]; // console.log(article.scrollTop) // 下拉 if(article.scrollTop=0){ console.log("下拉") // 如果ul列表到顶部,修改ul列表的偏移,显示“下拉刷新”,并准备触发下拉刷新功能,可自定义 let diff = list.offsetTop + touch.pageY - start; diff = diff = 0 ? diff : 0; list.style.top = diff +'px'; // ul.style.top = ul.offsetTop + 'px' start = touch.pageY; // console.log("list.style.top:",list.style.top) // 若ul偏移量过大,则修改文字,refresh置为true,配合'touchend'刷新 if(list.offsetTop=50) { refreshText.innerHTML = "释放刷新"; refresh = true; } }else{ // 上拉 console.log("上拉") // console.log("getScrollHeight:",that.getScrollHeight(list)) // console.log("getScrollTop:",that.getScrollTop(this)) // console.log("getClientHeight:",that.getClientHeight(this)) that.y = that.getScrollHeight(list) - that.getScrollTop(this) - that.getClientHeight(this); // 滚动触发touchmove事件 that.touchmoveHandle(); // 触底touchend事件 if(that.y = 10) { //这里向后台进行数据请求(第一页数据就是1,第二页就是2,然后将请求回来的数组(处理成数组)拼接起来) console.log("到底了!!") // addLi(); // 触发滚动结束事件 that.touchendHandle(); } } },false); // 滑动结束 article.addEventListener('touchend',function(event){ // 若'touchend'时,ul偏移,用setInterval循环恢复ul的偏移量 // 距离刷新有个20的距离 if(list.offsetTop=20) { refreshText.innerHTML = "加载中..."; // 若恢复时'refresh===true',刷新页面 if(refresh){ // 设置刷新 refreshDom.style.position = "static"; // 站位 list.style.top = 0; setTimeout(() = { location.reload(); }, 2000); } } },false); } // 事件触发 BScroll.prototype.trigger = function (type) { var events = this._events[type]; if (!events) { return; } var len = events.length; var eventsCopy = [].concat(toConsumableArray(events)); for (var i = 0; i  len; i++) { var event = eventsCopy[i]; // console.log("event:",event) var fn = event[0], context = event[1]; if (fn) { fn.apply(context, [].slice.call(arguments, 1)); } } }; // 初始化工作 eventMixin(BScroll); let scroll = new BScroll(article,{}) // 创建实例 // 监听滚动到底 scroll.on("touchend",(pos)={ // 继续加载更多 if(!finish ){ // 正在加载 if(loading){ return false; } loadingDom.style.display = "block"; addLi(); // 加载第二页数据 }else{ // 已记载完成 loadingDom.style.display = "block"; loadingDom.querySelector(".text").innerHTML = "已经到底了~" } }) /script/body/html

MJRefresh

  • An easy way to use pull-to-refresh
  • 用法简单的下拉刷新框架:一行代码搞定

Contents

<a id="支持哪些控件的刷新"></a>支持哪些控件的刷新

  • UIScrollViewUITableViewUICollectionViewUIWebView

<a id="如何使用MJRefresh"></a>如何使用MJRefresh

  • cocoapods导入:pod 'MJRefresh'
  • 手动导入:
    • MJRefresh文件夹中的所有文件拽入项目中
    • 导入主头文件:#import "MJRefresh.h"
Base                        Custom
MJRefresh.bundle            MJRefresh.h
MJRefreshConst.h            MJRefreshConst.m
UIScrollView+MJExtension.h  UIScrollView+MJExtension.m
UIScrollView+MJRefresh.h    UIScrollView+MJRefresh.m
UIView+MJExtension.h        UIView+MJExtension.m

<a id="已经超过上百个App正在使用MJRefresh"></a>已经超过上百个App正在使用MJRefresh

图片 2

<a id="MJRefresh类结构图"></a>MJRefresh类结构图

图片 3

  • 图中红色文字的类:可以直接拿来用
    • 下拉刷新控件的种类
      • 默认(Normal):MJRefreshNormalHeader
      • 动图(Gif):MJRefreshGifHeader
    • 上拉刷新控件的种类
      • 自动刷新(Auto)
        • 默认(Normal):MJRefreshAutoNormalFooter
        • 动图(Gif):MJRefreshAutoGifFooter
      • 自动回弹(Back)
        • 默认(Normal):MJRefreshBackNormalFooter
        • 动图(Gif):MJRefreshBackGifFooter
  • 图中非红色文字的类:拿来继承,用于自定义刷新控件
  • 关于如何自定义刷新控件,可以参考下图的类
![](https://upload-images.jianshu.io/upload_images/1478035-11d39fd7bdb9f2c9.png)

<a id="MJRefreshComponent.h"></a>MJRefreshComponent.h

/** 刷新控件的基类 */
@interface MJRefreshComponent : UIView
#pragma mark - 刷新状态控制
/** 进入刷新状态 */
- (void)beginRefreshing;
/** 结束刷新状态 */
- (void)endRefreshing;
/** 是否正在刷新 */
- (BOOL)isRefreshing;

#pragma mark - 其他
/** 根据拖拽比例自动切换透明度 */
@property (assign, nonatomic, getter=isAutomaticallyChangeAlpha) BOOL automaticallyChangeAlpha;
@end

<a id="MJRefreshHeader.h"></a>MJRefreshHeader.h

@interface MJRefreshHeader : MJRefreshComponent
/** 创建header */
+ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock;
/** 创建header */
+ (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action;

/** 这个key用来存储上一次下拉刷新成功的时间 */
@property (copy, nonatomic) NSString *lastUpdatedTimeKey;
/** 上一次下拉刷新成功的时间 */
@property (strong, nonatomic, readonly) NSDate *lastUpdatedTime;

/** 忽略多少scrollView的contentInset的top */
@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop;
@end

<a id="MJRefreshFooter.h"></a>MJRefreshFooter.h

@interface MJRefreshFooter : MJRefreshComponent
/** 创建footer */
+ (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock;
/** 创建footer */
+ (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action;

/** 提示没有更多的数据 */
- (void)endRefreshingWithNoMoreData;
/** 重置没有更多的数据(消除没有更多数据的状态) */
- (void)resetNoMoreData;

/** 忽略多少scrollView的contentInset的bottom */
@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom;

/** 自动根据有无数据来显示和隐藏(有数据就显示,没有数据隐藏) */
@property (assign, nonatomic) BOOL automaticallyHidden;
@end

<a id="MJRefreshAutoFooter.h"></a>MJRefreshAutoFooter.h

@interface MJRefreshAutoFooter : MJRefreshFooter
/** 是否自动刷新(默认为YES) */
@property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh;

/** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */
@property (assign, nonatomic) CGFloat triggerAutomaticallyRefreshPercent;
@end

<a id="参考"></a>参考

* 由于这个框架的功能较多,就不写具体文字描述其用法
* 大家可以直接参考示例中的MJTableViewController、MJCollectionViewController、MJWebViewController,更为直观快速

图片 4

<a id="下拉刷新01-默认"></a>下拉刷新01-默认

self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
   // 进入刷新状态后会自动调用这个block
}];
或
// 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];

// 马上进入刷新状态
[self.tableView.header beginRefreshing];

图片 5

(下拉刷新01-普通)

<a id="下拉刷新02-动画图片"></a>下拉刷新02-动画图片

// 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
MJRefreshGifHeader *header = [MJRefreshGifHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
// 设置普通状态的动画图片
[header setImages:idleImages forState:MJRefreshStateIdle];
// 设置即将刷新状态的动画图片(一松开就会刷新的状态)
[header setImages:pullingImages forState:MJRefreshStatePulling];
// 设置正在刷新状态的动画图片
[header setImages:refreshingImages forState:MJRefreshStateRefreshing];
// 设置header
self.tableView.mj_header = header;

图片 6

(下拉刷新02-动画图片)

<a id="下拉刷新03-隐藏时间"></a>下拉刷新03-隐藏时间

// 隐藏时间
header.lastUpdatedTimeLabel.hidden = YES;

图片 7

(下拉刷新03-隐藏时间)

本文由10bet发布于Web前端,转载请注明出处:iOS开发之______MJRefresh

关键词:

频道精选

最火资讯