下拉刷新对象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. LDA理解

    LDA只是一个求解思路. 1.理解LDA首先要理解EM算法,EM不能叫做一个算法,只是一个思想:它要求解的其实是一个极大似然估计,就是我用已知量去求解导致这个已知量出现的最大概率,而在这里又恰恰有点偏 ...

  2. java-多线程future等待返回

    多线程中需要返回值, java中有个fork/join模型, 没有细研究, 简单实用callable进行了返回 Thread1 package com.iwhere.easy.travel.test. ...

  3. 使用Xshell和Xftfp部署简单的项目

    最近本人偶尔接触到该如何部署项目,朋友要求截图,趁此之际,简单总结一下,以供大家分享,更希望各位大神指点,大家相互学习,有问题的勿喷. 1.使用环境:win 7+MyEclipse 2014 + to ...

  4. The version of SOS does not match the version of CLR you are debugging; SOS.dll版本不匹配; Dump文件不同环境mscordacwks.dll版本问题

    The version of SOS does not match the version of CLR you are debugging 和 PDB symbol for clr.dll not ...

  5. Oracle11g在Windows和Linux下imp导入表,exp导出表,sqluldr2导出表,sqlldr导入表

    Windows(Win10) 打开cmd 首先输入sqlplus,依次输入用户名.口令 C:\Users\hasee>sqlplus SQL*Plus: Release Production o ...

  6. 关于拓展jQuery功能插件的写法

    有两种方法: 1.jQuery.fn.extend() 用于将一个对象的内容合并到jQuery的原型,以提供新的jQuery实例方法 例子: <span id="test"& ...

  7. 修改Tomcat窗口名称

      做java开发,tomcat可以说是最常用的web容器.但是当开启多个tomcat容器之后,就不太容器轻松区别哪了个dos窗口是跑的哪个web应用了.此时可以给每一个窗口命名: 具体办法是:修改% ...

  8. 169.254地址无网关信息 ----- 解决方案 启动DHCP服务

    169.254.X.X是Windows操作系统在DHCP信息租用失败时自动给客户机分配的IP地址,.看到地址的时候没有网关. 解决方案   启动DHCP服务 1. 首先确认 路由器  DHCP 服务已 ...

  9. Golang 并发Groutine实例解读(二)

    go提供了sync包和channel机制来解决协程间的同步与通信. 一.sync.WaitGroup sync包中的WaitGroup实现了一个类似任务队列的结构,你可以向队列中加入任务,任务完成后就 ...

  10. [转] What is a Full Stack developer?

    期望一个凡人掌握开发过程中各个方面的知识,合理吗?也许不合理,但是Facebook正是要寻找这样的人.在一个OSCON会议上,一名Facebook的工程师告诉我的,他们只聘请“全能(Full stac ...