美文网首页
关于MJRefresh的源码

关于MJRefresh的源码

作者: 小李龍彪 | 来源:发表于2017-07-22 23:27 被阅读44次

    MJRefresh 是 OC 语言里面算是一款比较通用的刷新框架了,可以用于 UITableView 和 UICollectionView 的刷新,从而可以很方便的完成下拉刷新和上拉加载更多。而且可定制程度也很高。

    最近需要在公司的项目上加入一个刷新的特效,而公司项目用的刷新框架是 MJefresh ,所以在完成需求的同时就顺便把 MJRefresh 框架的源码给看了一遍。然后写下这篇文章总结一下。

    MJRefresh框架的结构是用子类继承的方式实现的,创建一个基类MJRefreshComponent,然后通过继承的方式,让MJRefreshHeader和MJRefreshFooter分别具备下拉刷新和上拉加载的功能。从继承机构来看可以分为三层,具体的继承关系可以从下面的图里看:

    其中五大核心类库

    MJRefreshComponent

    MJRefreshHeader

    MJRefreshFooter

    MJRefreshBackFooter

    MJRefreshAutoFooter

    其它的类都是在上面的基础上自定义的类。

    首先来看一下MJRefresh框架的基类:MJRefreshComponent

    MJRefreshComponent

    这个类作为框架的基类,涵盖了基类所具备的状态,回调block等,完成了以下几件事情:

    布局控件的位置。

    完成基本的设置工作。

    设置下拉刷新时的文本框。

    设置控件的所有状态。

    设置回调函数。

    添加监听。

    提供刷新,停止刷新接口。

    提供子类需要实现的方法。

    具体实现:

    定义控件的全部的状态

    定义控件的回调函数

    Target-Action类型的回调

    监听函数的实现

    开始刷新和停止刷新

    需要子类实现的方法

    其中代码中作者的注解可以看出框架具体的操作对象是 scrollView 而不是具体的 tableView 和 collectionView

    其中如果该类是 scrollView 或者 scrollView 子类就对其添加监听。

    其中isKindOfClass和isMemberOfClass的区别是需要关注的。

    然后MJRefreshHeader和MJRefreshFooter都继承MJRefreshComponent实现。

    MJRefreshHeader

    MJRefreshHeader继承MJRefreshComponent,它做了这几件事:

    初始化。

    设置header高度。

    重新计算下拉高度值。

    记录上一次刷新时间或者是第一次刷新时间。

    由contentOffset的变化,来切换状态(默认状态,可以刷新的状态,正在刷新的状态),实现方法是:scrollViewContentOffsetDidChange:。

    在切换状态时,执行相应的操作。实现方法是:setState:。

    两种创建方式(两种构造方法)

    重写父类方法,设置Y值 ,同时设置上次刷新时间

    状态切换

    重写控件所有状态的set方法,设置

    MJRefreshStateHeader

    这个类是MJRefreshHeader类的子类,它做了两件事:

    设置stateLabel和lastUpdatedTimeLabel的位置。

    根据控件状态的切换(默认状态,正在刷新状态),实现了这两个label显示的文字的切换。

    这里设置文字的方法有点儿类似按钮。将每一个状态对应的提示文字放入一个字典里面,key是状态的NSNumber形式。

    布局方法

    重写set方法,更新刷新时间

    1.作者通过使用block来让用户自己定义日期现实的格式,如果用户没有自定义,就使用作者提供的默认格式。

    2.默认格式的设置里,判断了是否是今日,是否是今年的情况。由具体时间显示label的文字是否显示年,月,日。

    MJRefreshNormalHeader

    MJRefreshNormalHeader 继承 MJRefreshStateHeader,它主要做了两件事:

    它在MJRefreshStateHeader上添加了_arrowView和loadingView。

    布局了这两个view并在Refresh控件的状态切换的时候改变这两个view的样式。

    作者同样是通过重写父类的三个方法实现子类自定义本类的控件。

    到此为止,我们已经从MJRefreshComponent到MJRefreshNormalHeader的实现过程看了一遍。可以看出,作者将prepare,placeSubviews以及setState:方法作为基类的方法,让下面的子类去一层一层实现。

    而每一层的子类,根据自身的职责,分别按照自己的方式来实现这三个方法:

    MJRefreshHeader: 负责header的高度和调整header自身在外部的位置。

    MJRefreshStateHeader:负责header内部的stateLabel和lastUpdatedTimeLabel的布局和不同状态下内部文字的显示。

    MJRefreshNormalHeader:负责header内部的loadingView以及arrowView的布局和不同状态下的显示。

    这样做的好处是,如果想要增加某种类型的header,只要在某一层上做文章即可。例如该框架里的MJRefreshGifHeader,它和MJRefreshNormalHeader属于同一级,都是继承于MJRefreshStateHeader。因为二者都具有相同形式的stateLabel和lastUpdatedTimeLabel,唯一不同的就是左侧的部分:

    MJRefreshNormalHeader的左侧是箭头。

    MJRefreshGifHeader的左侧则是一个gif动画。

    关于两种footerView的区别。

    BackFooter 自动弹回底部

    backFooter 是上拉出现加载 view ,然后在加载完以后就这个 view 就自动弹回底部的。即使是 tableView 或者是 collectionView 当数据量还不足以填充满整个界面的时候也是如此的。

    Auto Footer 自动刷新

    自动刷新方式是没有明显的上拉的动作,就是当滑动到最底部的时候,就自动加载。而当 tableView 或者 collectionView 的数据不足以填充满这个屏幕的时候,刷新的 view 也是现实在 最后一个数据项的下面一项。然后点击加载更多。

    总体而言,这个框架是在最基类里面实现了最基本的流程,而每个流程怎么处理则因为 header 和 Footer 的不同需要不同的逻辑处理。所以有 header 和 Footer 的子类。

    但是由于 Footer 的上拉有两种样式和情况,所以在 Footer 的基础上又实现两个类 backFooter 和 autoFooter 。

    相关文章

      网友评论

          本文标题:关于MJRefresh的源码

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