iOS MJRefresh 实现无感刷新

Posted 长沙火山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS MJRefresh 实现无感刷新相关的知识,希望对你有一定的参考价值。

前言

项目开发中用了MJRefres 刷新控件,每次上拉的时候都有个菊花转,需要下拉一下才能看到下一页的数据。产品提出需求,希望列表往下拉能直接出现下一页的数据,不需要出现加载的动画和等待时间。于是着手看了一下MJRefresh的源码,发现其提供了无感刷新(自动刷新)的方法。

从MJRefresh的继承图谱来看,下拉的自动刷新类为:MJRefreshAutoStateFooter。我们只需要继承这个类,然后把功能重写一下就可以实现了。

一、自定义上拉无感刷新

自己重新创建一个类:HSWuGanRefreshFooter,继承 MJRefreshAutoStateFooter。具体代码如下:

#import "MJRefreshAutoStateFooter.h"

@interface HSWuGanRefreshFooter : MJRefreshAutoStateFooter

@end
#import "HSWuGanRefreshFooter.h"

@interface HSWuGanRefreshFooter ()

@end

@implementation HSWuGanRefreshFooter

#pragma mark - 实现父类的方法
- (void)prepare 
    [super prepare];


- (void)placeSubviews
    [super placeSubviews];
    
    self.stateLabel.hidden = self.state != MJRefreshStateNoMoreData;


- (void)scrollViewContentSizeDidChange:(NSDictionary *)change

    [super scrollViewContentSizeDidChange:change];
    
    // 内容的高度
    CGFloat contentHeight = self.scrollView.mj_contentH + self.ignoredScrollViewContentInsetBottom;
    // 表格的高度
    CGFloat scrollHeight = self.scrollView.mj_h - self.scrollViewOriginalInset.top - self.scrollViewOriginalInset.bottom + self.ignoredScrollViewContentInsetBottom;
    // 设置位置和尺寸
    self.mj_y = MAX(contentHeight, scrollHeight);

@end

二、如何使用

//导入相关头文件
#import "HSWuGanRefreshFooter.h"

 //上拉加载更多
 self.tableView.mj_footer = [HSWuGanRefreshFooter footerWithRefreshingBlock:^
     self.page ++;
     [self requestData];
 ];

三、实现原理

通过分析其源码 MJRefreshAutoFooter 类可以发现其实就是将手动加载下一页变成了自动加载下一页。普通的下拉加载更多,是要用户手动的触发了列表底部的下拉刷新控件,而无感刷新只是将这一触发条件改成了监听屏幕滚动到哪个位置,变自动触发加载下一页的数据。

#import "MJRefreshFooter.h"

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

    [super scrollViewContentOffsetDidChange:change];
    
    if (self.state != MJRefreshStateIdle || !self.automaticallyRefresh || self.mj_y == 0) return;
    
    if (_scrollView.mj_insetT + _scrollView.mj_contentH > _scrollView.mj_h)  // 内容超过一个屏幕
        // 这里的_scrollView.mj_contentH替换掉self.mj_y更为合理
        if (_scrollView.mj_offsetY >= _scrollView.mj_contentH - _scrollView.mj_h + self.mj_h * self.triggerAutomaticallyRefreshPercent + _scrollView.mj_insetB - self.mj_h) 
            // 防止手松开时连续调用
            CGPoint old = [change[@"old"] CGPointValue];
            CGPoint new = [change[@"new"] CGPointValue];
            if (new.y <= old.y) return;
            
            // 当底部刷新控件完全出现时,才刷新
            [self beginRefreshing];
        
    

我们可以通过修改 triggerAutomaticallyRefreshPercent 的值改变触发加载下一页的时机,比如我们想要列表滑动到屏幕一半的时候开始加载下一页:

HSWuGanRefreshFooter *footer = [HSWuGanRefreshFooter footerWithRefreshingBlock:^
    self.page ++;
    [self requestData];
];
footer.triggerAutomaticallyRefreshPercent = 0.5;
self.tableView.mj_footer = footer;

资源下载:https://download.csdn.net/download/u010545480/86018895

以上是关于iOS MJRefresh 实现无感刷新的主要内容,如果未能解决你的问题,请参考以下文章

iOS MJRefresh 实现无感刷新

iOS用Sketch制作APP下拉刷新的GIF动画

iOS:详解MJRefresh刷新加载更多数据的第三方库

实现上下拉刷新MJRefresh

iOS UITableView-下拉刷新上拉加载

iOS UITableView-下拉刷新上拉加载