下拉刷新对象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