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. python标准库介绍——20 cStringIO 模块详解

    ==cStringIO 模块== ``cStringIO`` 是一个可选的模块, 是 ``StringIO`` 的更快速实现. 它的工作方式和 ``StringIO`` 基本相同, 但是它不可以被继承 ...

  2. Latex学习——长竖线及长括号

    Latex学习——长竖线及长括号   文章修改中要求把花括号和竖线变长,查了下发现下面的几种方法: 1.花括号“{ }”变长: \$         \left\{... content...... ...

  3. php分页函数示例代码

    分享一例php分页函数代码,用此函数实现分页代码很不错. 代码,php分页函数. <?php /* * Created on 2011-07-28 * Author : LKK , http:/ ...

  4. Linux,Windows中的相对路径、绝对路径

    1.Windows绝对路径:以盘符开始 如C:/a.txt相对路径:. 指的是当前目录.. 指的是挡圈目录的上一级目录./test表示当前目录下的test文件夹/test表示当前盘符下的test文件夹 ...

  5. python(34):为什么在Python里推荐使用多进程而不是多线程?

    最近在看Python的多线程,经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢?                  要知其然,更要知其所以然.所以有了下面的深 ...

  6. CTreeCtrl 父结点联动子结点CheckBox

    实现很简单,直接上代码: void CCheckBoxTreeDlg::OnNMClickTree1(NMHDR *pNMHDR, LRESULT *pResult) { // TODO: 在此添加控 ...

  7. 在jsp里面不要瞎用<!-- -->注释

    如图: SEVERE: Servlet.service() for servlet jsp threw exceptionorg.apache.jasper.JasperException: /ch1 ...

  8. Android开发日记(一)

    实现点击一个图片按钮跳转到一个动作ImageViewSchoolCard = (ImageView) view.findViewById(R.id.ImageViewLostThings); Imag ...

  9. JDBC的介绍2

    一.基础知识 1. 数据持久化 持久化(persistence):对象在内存中创建后,不能永久存在.把对象永久的保存起来就是持久化的过程.而持久化的实现过程大多通过各种关系数据库来完成. 持久化的主要 ...

  10. mysql自增id获取失败

    php 数据库pdo对象,如果是返回,如以下伪代码 function getData(){ return $data; } $data = getData(); $id = $data->las ...