下拉刷新对象RefreshObject

下拉刷新对象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-09-11 11:17:03

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

Android开源项目PullToRefresh下拉刷新功能详解2_Android

先看看效果图: 这里介绍的是PullToRefreshGridView的使用方法,和之前的PullToRefreshListView方法如出一辙,因为这个开源项目模块化很棒,所以很容易实现.等于说我们可以按照之前使用控件的方式来操作,不用考虑其他的问题.  思路:  1.写布局文件,放入可以下拉刷新的控件  2.找到下拉刷新的控件,设置监听器,并且在刷新方法中开启一个异步任务来操作  3.通过这个下拉刷新控件的getRefreshableView()方法来得到GridView对象,按照正常的操作

Android下拉刷新控件PullToRefresh实例解析_Android

Android中很多时候都会用到上下拉刷新,这是一个很常用的功能,Android的v4包中也为我们提供了一种原生的下拉刷新控件--SwipeRefreshLayout,可以用它实现一个简洁的刷新效果,但今天我们的主角并不是它,而是一个很火的第三方的上下拉刷新控件--PullToRefresh.PullToRefresh包括PullToRefreshScrollView.PullToRefreshListView.PullToRefreshGridView等等很多为我们提供的控件,我们可以在xml

做了一个listview的下拉刷新和底部自动加载,但我做完之后项目能运行,但就是始终加载不出来,求教

问题描述 做了一个listview的下拉刷新和底部自动加载,但我做完之后项目能运行,但就是始终加载不出来,求教 底下是代码 package caifu.life.ZHSQ.main; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os

js+html5+css3实现的滑动下拉刷新效果实例

今天想说的是如何自己操刀做一个js的下拉刷新(js + h5 + css3).既然是下拉,那么应用场景当然就是在手持设备上.在JavaScript的世界里,总是跟很多实用又华丽丽的效果接轨,这是一门很有色彩的编程语言.目前网络上也有很多非常优秀的js滑动插件,比如iscroll(最开始我们就是用这款插件,真心很好用,而且解决了很多html的问题).当然,我要讲的完全没办法和iscroll媲美,仅仅是简简单单的一角而已,主要目的在于对这点小知识的总结和分享. 之前也有讲过,移动设备上对CSS3和H

Android UI自定义ListView实现下拉刷新和加载更多效果_Android

关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就是不健全的.因为小巫近期要开发新浪微博客户端,需要实现ListView的下拉刷新,所以就想把这个UI整合到项目当中去,这里只是一个demo,可以根据项目的需要进行修改. 就不要太在乎界面了哈: 知道你们想要源码了,去下吧:http://download.csdn.net/detail/wwj_748/6373183 自定义ListView: package com.mar

Android仿新浪微博自定义ListView下拉刷新(4)_Android

自定义PullToRefreshListView继承ListView,在ListView头部添加一个下拉的头部布局.跟ListView用法完全一致. 该自定义Listview代码详解具体可参考: http://www.jb51.net/article/97845.htm 此处详细介绍Adapter的详细代码. 1.首先给Adapter绑定ListView布局. 2.其次创建一个层次对应组件的类,将对应的组件和对象进行关联,提高效率. 3.然后跟陆获得的图片路径异步下载图片,由于不知道该微博图片的

Android框架AndBase实现PullToRefrech下拉刷新

PullToRefrech下拉刷新..这个效果在绝大多数使用app貌似都使用的到..一个页面的.如果数据太多必然进行下拉..那么下拉之后就需要显示新的数据信息..这就是下拉刷新的完整体现.也可以说这种效果能够给用户一个更加良好的体验..那么我们看看下拉刷新到底是如何实现的.. 1.普通View的PullReferch   无论是普通View的下拉刷新还是ListView,还是GridView..下拉刷新实现的原理基本都是相同的..只不过实现上有一些简单的细节不太一样而已...首先先看看普通Vie

Android程序开发之Listview下拉刷新上拉(滑动分页)加载更多_Android

最近做的类似于微博的项目中,有个Android功能要使用到listview的向下拉刷新来刷新最新消息,向上拉刷新(滑动分页)来加载更多. 新浪微博就是使用这种方式的典型. 当用户从网络上读取微博的时候,如果一下子全部加载用户未读的微博这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了,其实这个分页可以做成客户端的分页,也可以做成服务器端的分页(点击加载时,从服务器对应的加载第N页就好了!!!).通过分

Android UI设计系列之自定义ListView仿QQ空间阻尼下拉刷新和渐变菜单栏效果(8)_Android

好久没有写有关UI的博客了,刚刚翻了一下之前的博客,最近一篇有关UI的博客:Android UI设计系列之自定义Dialog实现各种风格的对话框效果(7) ,实现各种风格效果的对话框,在那篇博客写完后由于公司封闭开发封网以及其它原因致使博客中断至今,中断这么久很是惭愧,后续我会尽量把该写的都补充出来.近来项目有个需求,要做个和QQ空间类似的菜单栏透明度渐变和下拉刷新带有阻尼回弹的效果.于是花点时间动手试了试,基本上达到了QQ空间的效果,截图如下:         通过观察QQ空间的运行效果,发现