MJRefresh是流行的下拉刷新控件。前段时间为了修复一个BUG。读了它的源代码。本文总结一下实现的原理

下拉刷新的基本原理

大部分的下拉刷新控件。都是用contentInset实现的。默认情况下。假设一个UIScrollView的左上角在导航栏的正下方,那么它的contentInset是64,而contentOffset是-64。继续下拉的话,contentOffset就会越来越小,假设上滑,contentOffset就会增大,直到左上角达到屏幕的左上角时,contentOffset刚好为0

默认情况下,假设下拉一个UIScrollView,在松手之后,会弹回初始的位置(导航栏下方)。

而大部分的下拉刷新控件,都是将自己放在UIScrollView的上方,起始y设置成负数。所以平时不会显示出来,仅仅有下拉的时候才会出现,放开又会弹回去。然后在loading的时候,暂时把contentInset增大,相当于把UIScrollView往下挤。于是下拉刷新的控件就会显示出来,然后刷新完毕之后。再把contentInset改回原来的值,实现回弹的效果

基本上,MJRefresh也是这么实现的

创建下拉刷新控件实例

从创建实例的代码開始:

MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{

    [myController loadCollectionDataNeedReset:YES withBlock:^{
[self.header endRefreshing];
[self reloadData];
}];
}];

调用的是一个工厂方法headerWithRefreshingBlock。这种方法定义在各种header控件的基类MJRefreshHeader里:

+ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock
{
MJRefreshHeader *cmp = [[self alloc] init];
cmp.refreshingBlock = refreshingBlock;
return cmp;
}

然后会调用init方法。因为MJRefreshHeader里并未定义init方法。而它的基类MJRefreshComponent里定义了,所以会进入到基类的初始化方法里:

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
// 准备工作
[self prepare]; // 默认是普通状态
self.state = MJRefreshStateIdle;
}
return self;
}

这里的关键是prepare方法。这种方法是第一个扩展点,详细的header(包含库提供的原生header。和用户自己定义的header)有哪些属性,样式是怎么样,都是在这种方法里实现的。每一个子类的prepare方法。都会调用父类的prepare方法。

所以在扩展的时候,公共的属性写在父类的prepare方法里,特有的属性写在子类的prepare方法里。比方,我们看一下MJRefreshStateHeader的:

- (void)prepare
{
[super prepare]; // 初始化文字
[self setTitle:MJRefreshHeaderIdleText forState:MJRefreshStateIdle];
[self setTitle:MJRefreshHeaderPullingText forState:MJRefreshStatePulling];
[self setTitle:MJRefreshHeaderRefreshingText forState:MJRefreshStateRefreshing];
}

总之。调用headerWithRefreshi

MJRefresh原理分析的更多相关文章

  1. Handler系列之原理分析

    上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信 ...

  2. Java NIO使用及原理分析(1-4)(转)

    转载的原文章也找不到!从以下博客中找到http://blog.csdn.net/wuxianglong/article/details/6604817 转载自:李会军•宁静致远 最近由于工作关系要做一 ...

  3. 原子类java.util.concurrent.atomic.*原理分析

    原子类java.util.concurrent.atomic.*原理分析 在并发编程下,原子操作类的应用可以说是无处不在的.为解决线程安全的读写提供了很大的便利. 原子类保证原子的两个关键的点就是:可 ...

  4. Android中Input型输入设备驱动原理分析(一)

    转自:http://blog.csdn.net/eilianlau/article/details/6969361 话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反 ...

  5. 转载:AbstractQueuedSynchronizer的介绍和原理分析

    简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...

  6. Camel运行原理分析

    Camel运行原理分析 以一个简单的例子说明一下camel的运行原理,例子本身很简单,目的就是将一个目录下的文件搬运到另一个文件夹,处理器只是将文件(限于文本文件)的内容打印到控制台,首先代码如下: ...

  7. NOR Flash擦写和原理分析

    NOR Flash擦写和原理分析 1. NOR FLASH 的简单介绍 NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute On Chip,即程序可以直 ...

  8. 使用AsyncTask异步更新UI界面及原理分析

    概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线 ...

  9. (转)Android 系统 root 破解原理分析

    现在Android系统的root破解基本上成为大家的必备技能!网上也有很多中一键破解的软件,使root破解越来越容易.但是你思考过root破解的 原理吗?root破解的本质是什么呢?难道是利用了Lin ...

随机推荐

  1. mysql-5.7 innodb 的并行任务调度详解

    一.innodb并行任务调度是什么: 这里要“考古”一下了,不然问题说不清楚.上大学的时候老师和我们说最初的计算机只有一个核心,并且一次也只能做一件事, 如果你有两件事要用到计算机,在第一件事没有做完 ...

  2. unity5 Orthographic模式相机视截体尺寸计算

    一,通过编辑器中数值计算. 如图,相机为Orthographic模式,其camera size为5.57,是什么含义呢,经过测量,发现视图中视截体的高度是5.57x2. 那么视截体的宽度怎么决定呢? ...

  3. tag标签数据库的设计

    方案一: 一个表,里面有个tags字段,存放以空格或逗号分隔的标签.缺点是长度受限,tag个数受限,查询like ‘%abc%’效率低 方案二: 同方案一,支持全文索引,或者用Lucence索引查询 ...

  4. jQuery 复选框全选/取消全选/反选

    jQuery实现的复选框全选/取消全选/反选及获得选择的值. 完整代码: <!DOCTYPE html> <html> <head> <script type ...

  5. F1 P R的理解

    F1 P R的理解 precision:查准率 recall:查全率,召回率 查准率,基于预测的结果,预测为正的样本中 由多少真正的正样本.即,真正为正的越多越好. 查全率,针对原来的正样本,有多少正 ...

  6. Install haroopad on centos7

    1.Install libs sudo yum install systemd-libs -y 2.Download haroopad goto haroopad1 download bin pack ...

  7. PairRDD中算子combineByKey图解

    1.combineByKey combine 为结合意思.    作用: 将RDD[(K,V)] => RDD[(K,C)] 表示V的类型可以转成C两者可以不同类型. def combineBy ...

  8. canvas相关api

    1.线性径变:ctx.createLinearGradient(): var grd=ctx.createLinearGradient(0,0,170,0); grd.addColorStop(0,' ...

  9. feginclient和hystrix的配置

    1.如果设置了 feign: hystrix: enabled: true 则 @FeignClient(value = "service-hi",configuration = ...

  10. 初始化git linux上传文件常见问题

    SSH生成id_rsa, id_rsa.pub后,连接服务器却报: Agent admitted failure to sign using the key 错误. 解决方法: 在当前用户下执行命令: ...