下拉刷新对象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. Java指定保留小数位数的方法

    package com.qiyuan.util; import java.math.BigDecimal; import java.math.RoundingMode; import java.tex ...

  2. lucene源码分析(1)基本要素

    1.源码包 core: Lucene core library analyzers-common: Analyzers for indexing content in different langua ...

  3. IE浏览器版本的判断

    var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 && userAgent.indexOf(; //判断是否IE< ...

  4. 【手记】解决启动SQL Server Management Studio 17时报Cannot find one or more components...的问题

    刚装好SSMS 17.1准备体验,弹出: 一番搜索,普遍办法都是安装VS2015独立shell.删除某个注册表项什么的,没用,首先这个shell我是装了的,然后也没有那个注册表项.我自己尝试过重装sh ...

  5. 面向对象(static关键字的特点)

    static关键字的特点 * a:随着类的加载而加载 * b:优先于对象存在 * c:被类的所有对象共享 * 举例:咱们班级的学生应该共用同一个班级编号. * 其实这个特点也是在告诉我们什么时候使用静 ...

  6. HDU 1695 GCD 欧拉函数+容斥定理 || 莫比乌斯反演

    GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  7. [选译]MySQL5.7以上Zip版官方安装文档

    前言 在windows上安装Zip版MySQL(选译) 学习mysql的朋友们会发现5.7+版本的mysql变得比以前难安装了许多(当然我们可以选择installer版本,但是这样总感觉对学习mysq ...

  8. Dijkstra Java

    https://leetcode.com/problems/network-delay-time/ /* Java program to find a Pair which has maximum s ...

  9. WPF流程图制作系列相关基础二

       我们现在知道 thumb ,可以让用户自行拖动其在 canvas上移动,在这个而基础上 我们可以试着往流程图方向靠近一下. 我们知道,流程图,都是一个一个的流程块,然后用线连起来的,这一个一个的 ...

  10. vue的v-html插值样式问题

    content使用html插入文本和图片 使用scoped样式,渲染失败. 原因: 解决方案: 采用全局样式 或另外再加style标签单独渲染