zoukankan      html  css  js  c++  java
  • MJRefresh原理分析

    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

  • 相关阅读:
    iOS设置app应用程序文件共享
    UIButton 一个控件 实现 左图标右文本的效果
    centos7 修改selinux 开机导致 faild to load SELinux policy freezing 错误
    centos7 使用 omnibus包安装方式,安装 gitlab7.4
    iOS app 企业内部发布及HTTPS服务器配置
    centos7 安装mariaDB 以及 phpmyadmin的安装
    centos7 最小化安装 无 ifconfig,netstat 的安装
    windows 下使用 Filezilla server 搭建 ftp 服务器
    PostgreSQL 登录时在命令行中输入密码
    Docker Error response from daemon: driver failed programming external connectivity on endpoint webserver
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7346633.html
Copyright © 2011-2022 走看看