美文网首页将来跳槽用iOS开发笔录iOS开发历程
iOS 下拉刷新思路(自己写一个下拉刷新)

iOS 下拉刷新思路(自己写一个下拉刷新)

作者: 16哥哥 | 来源:发表于2016-12-21 16:18 被阅读536次

    在现在的iOS开发过程中,都会需要有下拉刷新的功能,这也成为了大部分 App 必备的交互方式。对于新手,往往需要学习使用第三方来完成这个功能,现在比较流行的开源的下拉刷新控件如 MJRefresh 。其实现原理一共有两种,第一种是利用 UITabelView 的headerView ,另一种是利用 UIScrollView 的类拓展 ,后一种方式是更被人接受的。

    首先介绍一下我这个DEMO的下拉刷新的使用方法:

    demo效果图

    只需要一句代码就可以实现下拉加载的功能。下面就开始准备工作吧!

    在自己写一个下拉刷新之前,需要了解几个scrollView的属性:

    contentSize:视图的滚动范围

    contentOffset:这个属性在这里主要用contentOffset.y来监听视图滚动事件

    contentInset:这个属性主要是用来设置刷新视图的frame

    下拉刷新的功能实现主要就是监听视图滚动的contentOffset.y来改变下拉刷新的状态,并提示用户接下来的操作。

    废话不多说,进入主题,开始自己写一个下拉刷新:(下面是下拉刷新的几个重要步骤)

    一。首先,创建一个UIScrollView的类拓展,和headerView文件

    二。既然选择使用UIScrollView的拓展来实现,首先要了解到,类拓展不能自己添加属性,所以需要考虑用runtime来实现添加,下面是代码:

    @property (nonatomic , strong) RefreshHeaderView *headerView;

    @property (nonatomic , strong) RefreshFooterView *footerView;

    @property (nonatomic , strong) headerRefresh headerBlock;

    @property (nonatomic , strong) footerRefresh footerBlock;

    我在.h文件中添加了这几个属性,现在需要结合runtime来进行添加:(记得添加runtime的头文件 )

    // 实现属性添加

    - (void)setHeaderView:(RefreshHeaderView *)headerView{

    objc_setAssociatedObject(self, @"RefreshHeaderView", headerView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    -(RefreshHeaderView *)headerView{

    return objc_getAssociatedObject(self, @"RefreshHeaderView");

    }

    - (void)setHeaderBlock:(headerRefresh)headerBlock{

    objc_setAssociatedObject(self, @"headerRefresh", headerBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    - (headerRefresh)headerBlock{

    return objc_getAssociatedObject(self, @"headerRefresh");

    }

    - (void)setFooterView:(RefreshFooterView *)footerView{

    objc_setAssociatedObject(self, @"RefreshFooterView", footerView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    - (RefreshFooterView *)footerView{

    return objc_getAssociatedObject(self, @"RefreshFooterView");

    }

    - (void)setFooterBlock:(footerRefresh)footerBlock{

    objc_setAssociatedObject(self, @"footerRefresh", footerBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    - (footerRefresh)footerBlock{

    return objc_getAssociatedObject(self, @"footerRefresh");

    }

    这样,scrollView就成功添加了这些属性。

    三。接下来就是实现下拉刷新视图的添加方法和方法的实现:

    这个项目是使用RAC来做的,其中的RACObserve类似OC中的KVO,也可以说block中的代码写在KVO监听方法中就可以了。(有想了解RAC也可以留言)通过UIScrollView的dragging属性来判断用户的手指是否离开屏幕,在这里我创建了一个枚举来控制下拉刷新:

    typedef NS_ENUM(NSInteger, RefreshStatus) {

    // 刷新状态

    RefreshStatusWillRefresh = 0,

    RefreshStatusBeginRefresh = 1,

    RefreshStatusWillLoadMore = 2,

    RefreshStatusBeginLoadMore = 3,

    RefreshStatusCancelRefresh = 4

    };

    四。在状态等于RefreshStatusBeginRefresh时,调用下拉刷新回调来实现刷新数据。还需要一个停止刷新的方法,方法中主要重新设置一下视图的contentInset = UIEdgeInsetsMake(0, 0, 0, 0);就可以了。下拉刷新的视图在headerView里面设置,如下:

    - (void)endHeaderRefresh{

    // 隐藏下拉刷新

    [UIView animateWithDuration:3 animations:^{

    self.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);

    self.headerView.is_refresh = NO;

    }];

    }

    这篇文章主要是将下拉刷新的几个主要步骤,懂了这几个步骤,自己写一个下拉加载就很轻松了。过几天发一篇上拉加载的实现原理的文章。

    想自己手动封装一个下拉刷新,上拉加载控件的同学可以来看看啦,非常简单的实现方法,感觉好的话记得给个star  附链接 https://github.com/jijiawei/JWRefresh

    相关文章

      网友评论

      • b4067f4d3883:在scrollView的类目里,不会去走ScrollView的代理方法吗?我看你的Demo里是直接监听offset的值。
      • 林中悍匪:你好,有两个疑问想问一下,
        第一是设置headerView的高度,在header里面已经设置了self.frame = CGRectMake(0, -50, SW, 50);为什么在添加header的时候又self.headerView = [[JWRefreshHeaderView alloc]initWithFrame:CGRectMake(0, -50, SW, 50)];这样设置了一遍。在添加headerView时候是不是设置的y并没有什么作用。
        第二 if ([keyPath isEqualToString:@"JW_RefreshStatu"]) {
        if (!self.dragging) {}
        这个方法似乎都不会走到,请问是为了防止什么情况呢?
        林中悍匪:@16哥哥 第二个问题。你说的那个情况,他会走这里else if([self.RefreshStatu isEqualToString:@"JW_RefreshStatusWillRefresh"]){// 下拉刷新
        那么if ([keyPath isEqualToString:@"JW_RefreshStatu"]) {
        if (!self.dragging) {}
        这个方法会不会重复了呢
        林中悍匪:@16哥哥 博主客气了,我是自己写了一遍,发现你这么写,不懂是为什么,就问了一下。
        16哥哥:@林中悍匪 第一个问题,当时疏忽了,有时间改,可能设置重复了
        第二个问题,当你下拉的时候,刚刚改变成松手下拉刷新的状态时松手,就会走这个方法,因为只根据tableView的偏移量判断,在临界点刷新时可能会出错。
        谢谢你能看的这么仔细:smile:
      • 5ee14485e803:挺好,看了你这篇文章,原理一目了然
        5ee14485e803:@16哥哥 你这不就是OC版的吗?
        16哥哥:@小雨的名字 谢谢,有空更新一篇OC版本的
      • 塔米尔:jiangjunios@163.com谢谢!已收藏
        16哥哥:@塔米尔 已发送
      • Anday_:zdqwyyx@163.com给个赞:+1:
        16哥哥:@Anday_ 不着急,慢慢来,毕竟这个还用到了runtime 等你接触了再来看这个,收获会很大的
        Anday_:@16哥哥 刚学ios,看代码有点困难
        16哥哥:@Anday_ 最近项目上线,不好意思,Demo 已发
      • 4decac6f2087:469147356@qq.com 求demo
        16哥哥:@余余余余余余 已发,请查收:blush:
      • 伊织随意写:1625608596@qq.com
        Demo还能发吗?
        伊织随意写:@16哥哥 谢谢,收到了
        16哥哥:@Chris的祝福 已发~最近比较忙,不好意思:blush:
      • 打瞌睡de小男孩:写的不错,赞一个,我最近也在试着封装,遇到点问题,麻烦楼主分享下demo,我参考下,谢谢啦 rebornlong@qq.com
        16哥哥:已发~:smile:
      • 潇湘候晨雪:3404567923@qq.com
        潇湘候晨雪:@16哥哥 收到了,感谢!
        16哥哥:已发,抱歉,发晚了~:smile:
      • iOS学习着ne:1024911523@qq.com
        iOS学习着ne:@16哥哥 谢谢呀:smile:
        16哥哥:@我来学习你信吗 已发:smile:

      本文标题:iOS 下拉刷新思路(自己写一个下拉刷新)

      本文链接:https://www.haomeiwen.com/subject/jqvqvttx.html