下拉刷新对象RefreshObject

效果

说明

1. 分离了动画实现与刷新逻辑

2. 你可以根据自己的需要,设计自己的动画效果,你的动画只需要继承协议,实现协议里面的方法即可

3. 本设计方案是用的组件方式,代码复用率很高,灵活性很强

源码

https://github.com/YouXianMing/RefreshObject

//
// RefreshObjectAnimationProtocal.h
// TableViewRefresh
//
// Created by YouXianMing on 15/6/25.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
// #import <Foundation/Foundation.h> @protocol RefreshObjectAnimationProtocal <NSObject> @required
- (void)animationWithPercent:(CGFloat)percent;
- (void)startRefreshAnimation;
- (void)endRefreshAnimation; @end
//
// RefreshObject.h
// UIScrollView
//
// Created by YouXianMing on 15/6/24.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class RefreshObject; typedef enum : NSUInteger { NORMAL_STATE, // 正常状态
REFRESH_STATE, // 刷新状态 } ERefreshState; @protocol RefreshObjectDelegate <NSObject> @required
/**
* 开始刷新
*
* @param refreshObject
*/
- (void)startRefreshing:(RefreshObject *)refreshObject; /**
* 结束刷新
*
* @param refreshObject
*/
- (void)endRefresh:(RefreshObject *)refreshObject; - (void)moving:(RefreshObject *)refreshObject offset:(CGFloat)offset percent:(CGFloat)percent; @end @interface RefreshObject : NSObject /**
* 代理
*/
@property (nonatomic, weak) id <RefreshObjectDelegate> delegate; /**
* 当前状态
*/
@property (nonatomic, readonly) ERefreshState state;
@property (nonatomic) CGFloat height;
@property (nonatomic, weak) UIScrollView *scrollView; /**
* === 子类可以重写该方法实现新的刷新效果 ===
*
* 开始刷新
*/
- (void)beginRefreshing; /**
* === 子类可以重写该方法实现新的刷新效果 ===
*
* 结束刷新
*/
- (void)endRefresh; @end
//
// RefreshObject.m
// UIScrollView
//
// Created by YouXianMing on 15/6/24.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
// #import "RefreshObject.h" @interface RefreshObject () @end @implementation RefreshObject - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // 当前位置
float currentPostion = _scrollView.contentOffset.y; if (_scrollView.isDragging) {
// 拖拽中 if (_state == NORMAL_STATE) { // 获取位移的信息
if (_delegate) { CGFloat percent = ;
if (currentPostion <= ) {
percent = -currentPostion / _height;
} [_delegate moving:self offset:currentPostion percent:percent];
}
} } else {
// 停止拖拽 if (currentPostion < -_height) { [self beginRefreshing];
}
} } - (void)beginRefreshing { if (_state == NORMAL_STATE) {
_state = REFRESH_STATE; if (_delegate) {
[_delegate startRefreshing:self];
} [UIView animateWithDuration:0.3 animations:^{
_scrollView.contentInset = UIEdgeInsetsMake(_height, , , );
} completion:^(BOOL finished) { }];
}
} - (void)endRefresh { if (_delegate) {
[_delegate endRefresh:self];
} [UIView animateWithDuration:0.3f animations:^{
_scrollView.contentInset = UIEdgeInsetsMake(, , , );
} completion:^(BOOL finished) {
_state = NORMAL_STATE;
}];
} @end
//
// UIScrollView+RefreshObject.h
// UIScrollView
//
// Created by YouXianMing on 15/6/24.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
// #import <UIKit/UIKit.h>
#import "RefreshObject.h" @interface UIScrollView (RefreshObject) /**
* 需要主动赋值
*/
@property (nonatomic, strong) RefreshObject *refreshObject; /**
* 添加观察者
*/
- (void)addObserver; /**
* 移除观察者
*/
- (void)removeObserver; @end
//
// UIScrollView+RefreshObject.m
// UIScrollView
//
// Created by YouXianMing on 15/6/24.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
// #import "UIScrollView+RefreshObject.h"
#import <objc/runtime.h> @implementation UIScrollView (RefreshObject) #pragma mark - 添加属性 @dynamic refreshObject; NSString * const _recognizerRefreshObject = @"recognizerRefreshObject"; - (void)setRefreshObject:(RefreshObject *)refreshObject { objc_setAssociatedObject(self, (__bridge const void *)(_recognizerRefreshObject), refreshObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
} - (RefreshObject *)refreshObject { return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerRefreshObject));
} #pragma mark - - (void)addObserver { if (self.refreshObject && self.refreshObject.scrollView == nil) { // 获取scrollView
self.refreshObject.scrollView = self; // 添加监听
[self addObserver:self.refreshObject
forKeyPath:@"contentOffset"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:nil];
}
} - (void)removeObserver { if (self.refreshObject) { // 移除监听
[self removeObserver:self.refreshObject
forKeyPath:@"contentOffset"]; self.refreshObject.scrollView = nil;
self.refreshObject = nil;
}
} @end

细节

继承协议 RefreshObjectAnimationProtocal 并实现协议方法即可,使用的话,如下所示

下拉刷新对象RefreshObject的更多相关文章

  1. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法

    C#构造方法(函数)   一.概括 1.通常创建一个对象的方法如图: 通过  Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...

  2. IOS第四天-新浪微博 -存储优化OAuth授权账号信息,下拉刷新,字典转模型

    *************application - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOpti ...

  3. react + iscroll5 实现完美 下拉刷新,上拉加载

    经过几天的反复折腾,总算做出一个体验还不错的列表页了,主要支持了下拉刷新,上拉加载两个功能. 一开始直接采用了react-iscroll插件,它是基于iscroll插件开发的组件.但是开发过程中,发现 ...

  4. Windows phone应用开发[22]-再谈下拉刷新

    几周之前在博客更新一篇Windows phone应用开发[18]-下拉刷新 博文,有很多人在微博和博客评论中提到了很多问题.其实在实际项目中我基于这篇博文提出解决问题思路优化了这个解决方案.为了能够详 ...

  5. Windows phone应用开发[18]-下拉刷新

    在windows phone 中采用数据列表时为了保证用户体验常遇到加载数据的问题.这个问题普遍到只要你用到数据列表就要早晚面对这个问题. 很多人会说这个问题已经有解决方案. 其实真正问题并不在于如何 ...

  6. 【转载】 Android PullToRefresh (ListView GridView 下拉刷新) 使用详解

    Android下拉刷新pullToRefreshListViewGridView 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/3 ...

  7. Android开发学习之路-下拉刷新以及GridView的使用

    GridView是类似于ListView的控件,只是GridView可以使用多个列来呈现内容,而ListView是以行为单位,所以用法上是差不多的. 主布局文件,因为要做下拉刷新,所以加了一个Prog ...

  8. [Android]下拉刷新控件RefreshableView的实现

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4172483.html 需求:自定义一个ViewGroup,实现 ...

  9. Android PullToRefresh (GridView 下拉刷新上拉加载)

    做这个需要自己去git hub上下载个pull-to-refresh 里面有个library为依赖包自己导到自己的项目中 (下载地址:https://github.com/chrisbanes/And ...

随机推荐

  1. MySQL 继续-- Win7 安装及后续工作

    学MySQL 差不多了,就要实战,实战怎么能少得了软件. 一  : 下载软件 可以到 MySQL 官网直接下载 (社区版) : http://dev.mysql.com/downloads/mysql ...

  2. Mysql5.5升级到5.6步骤详解 小版本大版本

    http://blog.csdn.net/i_team/article/details/9935693 小版本升级,先关闭数据库,然后mv直接全部替换掉mysql目录下的bin/ ,lib/ ,sha ...

  3. springboots 配置文件

    1.build.gradle buildscript { // 声明变量 ext { springBootVersion = '1.5.2.RELEASE' } // 仓库 repositories ...

  4. 2 字节的 UTF-8 序列的字节 2 无效 解决方法

    2 字节的 UTF-8 序列的字节 2 无效 解决方法: 用记事本打开xml文件,另存为 编码 选择 UTF-8,保存替换掉之前的文件,解决问题

  5. [PHP] 深入理解PHP内核:变量及数据类型

    1.现实生活中我们会找一个小箱子来存放物品,一来显得不那么凌乱,二来方便以后找到.计算机也是这个道理,我们需要先在内存中找一块区域,规定用它来存放数据,并起一个好记的名字,方便以后查找.这块区域就是“ ...

  6. tcpcopy简介

    本文内容是整理自 王斌的博客(http://blog.csdn.net/wangbin579)和郑钧的博客(http://www.cnblogs.com/zhengyun_ustc),以便让自己可以有 ...

  7. MyBatis入门(二)—— 输入映射和输出映射、动态sql、关联查询

    一.输入映射和输出映射 1. parameterType(输入类型) 1.1 传递简单类型 <select id="getUserById" parameterType=&q ...

  8. K8S基础概念

    一.核心概念 1.Node Node作为集群中的工作节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod.Node上运行着Kubernetes的Kubelet.kube ...

  9. HDU1560(KB2-E IDA星)

    DNA sequence Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  10. 进程间通信IPC -- 管道, 队列

    进程间通信--IPC(Inter-Process Communication) 管道 from multiprocessing import Pipecon1,con2 = Pipe()管道是不安全的 ...