https://github.com/YouXianMing

下拉刷新对象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 并实现协议方法即可,使用的话,如下所示

 

posted @ 2015-06-25 22:46  YouXianMing  阅读(826)  评论(0编辑  收藏  举报