您的位置:首页 > 移动开发 > Objective-C

下拉刷新对象RefreshObject

2015-06-25 22:46 751 查看
下拉刷新对象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 并实现协议方法即可,使用的话,如下所示

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: