下拉刷新对象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 = 0;
                if (currentPostion <= 0) {
                    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, 0, 0, 0);
        } completion:^(BOOL finished) {

        }];
    }
}

- (void)endRefresh {

    if (_delegate) {
        [_delegate endRefresh:self];
    }

    [UIView animateWithDuration:0.3f animations:^{
        _scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    } 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 并实现协议方法即可,使用的话,如下所示

时间: 2024-10-14 10:41:30

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

自定义下拉刷新控件

一.功能效果 1.在很多app中,在信息展示页面,当我们向下拖拽时,页面会加载最新的数据,并有一个短暂的提示控件出现,有些会有加载进度条,有些会记录加载日期.条目,有些还带有加载动画.其基本实现原理都相仿,本文中将探讨其实现原理,并封装出一个简单的下拉刷新控件 2.自定义刷新工具简单的示例 二.系统提供的下拉刷新工具 1.iOS6.0以后系统提供了自己的下拉刷新的控件:UIRefreshControl .例如,refreshControl,作为UITableViewController中的一个属

Android的下拉刷新带进度条效果

首先看一下运行效果图,程序的下拉刷新参考了视频,在视频页面也提供了源码下载, http://www.imooc.com/learn/135 本篇主要说在此基础上增加了进度条的快速旋转和递增递减处理,在文章最后也会给出源码,这里主要描述一下所用的一个类 RoundProgressBar package com.cayden.listview; import android.content.Context; import android.content.res.TypedArray; import

Android UI设计之&lt;十&gt;自定义ListView,实现QQ空间阻尼下拉刷新和渐变菜单栏效果

转载请注明出处:http://blog.csdn.net/llew2011/article/details/51559694 好久没有写有关UI的博客了,刚刚翻了一下之前的博客,最近一篇有关UI的博客是在2014年写的:Android UI设计之<七>自定义Dialog,实现各种风格效果的对话框,在那篇博客写完后由于公司封闭开发封网以及其它原因致使博客中断至今,中断这么久很是惭愧,后续我会尽量把该写的都补充出来.近来项目有个需求,要做个和QQ空间类似的菜单栏透明度渐变和下拉刷新带有阻尼回弹的效

vue之better-scroll的封装,包含下拉刷新,上拉加载功能及UI(核心为借鉴,我仅仅是给轮子套上了外胎...)

先发原文作者.地址等信息.我把内容全部搬过来了,也可以去看原文.内容绝对是满满的干货,给原作者点赞!(我添加的内容在转载过来的后面,内容不多) 作者: ustbhuangyi 链接:http://www.imooc.com/article/18232 来源:慕课网 在我们日常的移动端项目开发中,处理滚动列表是再常见不过的需求了,以滴滴为例,可以是这样竖向滚动的列表,如图所示: 也可以是横向滚动的导航栏,如图所示: 可以打开"微信 -> 钱包->滴滴出行"体验效果. 我们在实

自定义控件基础02_下拉刷新_侧拉菜单_自定义属性

自定义控件02 自定义控件 ①,纯粹自定义绘制 ②,在原生的基础上追加功能. 1,下拉刷新功能(继承ListView追加功能)(下拉刷新,加载更多,两个功能) 1.1 下拉刷新 ①创建一个类,继承ListView 创建自定义适配器,设置数据 额外:自定义控件会放到view包下 ②自定义控件的头(即下拉的时候显示的view) 推荐名称initHeaderView();在构造方法中初始化这个头 this.addHeaderView()//添加一个头布局的控件,在listView顶部添加一个头 头部u

2.下拉刷新、二维码

下拉刷新 pulltorefresh 支持listview,webview,gridview,expandableListview众多控件 1,lv_list = refreshListView.getRefreshableView();//需要拿到refreshListView这个组合控件里面的具体的listview,才可以设置adapter 2.refreshListView.setRefreshing();//开始加载数据的时候.应该显示.正在刷新 3.refreshListView.on

swift详解之十九--------------UITableView的基本操作(下拉刷新,新增删除,分组,检索等)

UITableView的基本操作(下拉刷新,新增删除,分组,检索等) 注:本小结总结UITableview的一些基本用法 UITbleView继承自UIScrollView,只能用来显示一列数据(目前就只认识到这里),纵向滑动. 一般有两种方式来实现,直接用UITableViewController , 占满整个屏幕 .不用手动实现UITableViewDataSource 和UITableViewDelegate .另一种方式在UIViewController 中.我们看看这种方式 let t

Xamarin.Form 下拉刷新动画

好像园子里对 Xamarin 感兴趣的人很少啊... 来, 先给各位爷们逗个笑, 本山大爷本色出演: 照例, 上源码: https://github.com/gruan01/ListViewExtend 目前只有 WP 的效果, Android 还在研究, IOS 的还没计划. ------------------------------------------------------ Xamarin.Form 的 ListView 只支持下拉刷新 (这里有用法), 上拉 加载更多 没有对应的事

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

需求:自定义一个ViewGroup,实现可以下拉刷新的功能.下拉一定距离后(下拉时显示的界面可以自定义任何复杂的界面)释放手指可以回调刷新的功能,用户处理完刷新的内容后,可以调用方法onCompleteRefresh()通知刷新完毕,然后回归正常状态.效果如下:     源代码:RefreshableView(https://github.com/wangjiegulu/RefreshableView) 分析: 我们的目的是不管什么控件,只要在xml中外面包一层标签,那这个标签下面的所有子标签所