多的不多说直接上代码
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
typedef enum{
EGOOPullRefreshPulling = 0,
EGOOPullRefreshNormal,
EGOOPullRefreshLoading,
} EGOPullRefreshState;
@protocol EGORefreshTableHeaderDelegate;
@interface EGORefreshTableHeaderView : UIView {
id _delegate;
EGOPullRefreshState _state;
UILabel *_lastUpdatedLabel;
UILabel *_statusLabel;
CALayer *_arrowImage;
UIActivityIndicatorView *_activityView;
}
@property(nonatomic,assign) id <EGORefreshTableHeaderDelegate> delegate;
//更新下拉刷新时间
- (void)refreshLastUpdatedDate;
//下拉判断状态的时候调用的方法
- (void)egoRefreshScrollViewDidScroll:(UIScrollView *)scrollView;
//结束下拉判断状态的时候调用的方法
- (void)egoRefreshScrollViewDidEndDragging:(UIScrollView *)scrollView;
//完成数据加载调用的协议方法
- (void)egoRefreshScrollViewDataSourceDidFinishedLoading:(UIScrollView *)scrollView;
@end
@protocol EGORefreshTableHeaderDelegate
//下拉到一定程度是调用的协议方法
- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view;
//正在加载调用的协议方法
- (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView*)view;
@optional
//返回下拉刷新时间的协议方法
- (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView*)view;
@end
#import "EGORefreshTableHeaderView.h"
#define TEXT_COLOR [UIColor colorWithRed:87.0/255.0 green:108.0/255.0 blue:137.0/255.0 alpha:1.0]
#define FLIP_ANIMATION_DURATION 0.18f
@interface EGORefreshTableHeaderView (Private)
- (void)setState:(EGOPullRefreshState)aState;
@end
@implementation EGORefreshTableHeaderView
@synthesize delegate=_delegate;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
//初始化方法中创建显示时间、显示加载文本提示的lebel和显示加载图片提示的视图
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;//设置当前视图随父视图的宽度变化而变化
self.backgroundColor = [UIColor colorWithRed:226.0/255.0 green:231.0/255.0 blue:237.0/255.0 alpha:1.0];
//创建显示时间的label
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 30.0f, self.frame.size.width, 20.0f)];
label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
label.font = [UIFont systemFontOfSize:12.0f];
label.textColor = TEXT_COLOR;
label.shadowColor = [UIColor colorWithWhite:0.9f alpha:1.0f];
label.shadowOffset = CGSizeMake(0.0f, 1.0f);
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
[self addSubview:label];
_lastUpdatedLabel=label;
[label release];
//创建显示刷新状态的label
label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 48.0f, self.frame.size.width, 20.0f)];
label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
label.font = [UIFont boldSystemFontOfSize:13.0f];
label.textColor = TEXT_COLOR;
label.shadowColor = [UIColor colorWithWhite:0.9f alpha:1.0f];
label.shadowOffset = CGSizeMake(0.0f, 1.0f);
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
[self addSubview:label];
_statusLabel=label;
[label release];
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(25.0f, frame.size.height - 65.0f, 30.0f, 55.0f);
//设置layer在view上以某种形式适应
layer.contentsGravity = kCAGravityResizeAspect;
layer.contents = (id)[UIImage imageNamed:@"blueArrow.png"].CGImage;
// 判断设备版本,因为一些iOS特性是在最后新增的,要求设备配置高一些,所以做一下判断
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
//在ios 4.0 之后为了实现适配多种分辨率新增的一个方法
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
layer.contentsScale = [[UIScreen mainScreen] scale];
}
#endif
[[self layer] addSublayer:layer];
_arrowImage=layer;
//创建一个类似于菊花的控件
UIActivityIndicatorView *view = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
view.frame = CGRectMake(25.0f, frame.size.height - 38.0f, 20.0f, 20.0f);
[self addSubview:view];
_activityView = view;
[view release];
//根据设置下拉的状态来设置此控件中UI的显示
[self setState:EGOOPullRefreshNormal];
}
return self;
}
#pragma mark -
#pragma mark Setters
//更新label中下拉刷新时间的显示
- (void)refreshLastUpdatedDate {
//判断代理对象是否实现了egoRefreshTableHeaderDataSourceLastUpdated代理协议方法
if ([_delegate respondsToSelector:@selector(egoRefreshTableHeaderDataSourceLastUpdated:)]) {
NSDate *date = [_delegate egoRefreshTableHeaderDataSourceLastUpdated:self];
//通过NSDateFormatter这个对象设置日期时间显示的样式
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setAMSymbol:@"AM"];
[formatter setPMSymbol:@"PM"];
[formatter setDateFormat:@"MM/dd/yyyy hh:mm:a"];
//更新label中的显示内容
_lastUpdatedLabel.text = [NSString stringWithFormat:@"Last Updated: %@", [formatter stringFromDate:date]];
// 将时间保存到本地
[[NSUserDefaults standardUserDefaults] setObject:_lastUpdatedLabel.text forKey:@"EGORefreshTableView_LastRefresh"];
[[NSUserDefaults standardUserDefaults] synchronize];
[formatter release];
} else {
_lastUpdatedLabel.text = nil;
}
}
- (void)setState:(EGOPullRefreshState)aState{
//判断下拉刷新控件不同的状态对应不同的ui的展示
switch (aState) {
//1.下拉到一定程度的状态
case EGOOPullRefreshPulling:
//下拉到一定程度显示的label
_statusLabel.text = NSLocalizedString(@"Release to refresh...", @"Release to refresh status");
//这个地方用到了核心动画的内容
[CATransaction begin];
[CATransaction setAnimationDuration:FLIP_ANIMATION_DURATION];
//通过旋转设置图片尖头的方向,尖头的旋转就是一个动画的过程
_arrowImage.transform = CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.0f);
[CATransaction commit];
break;
//2.刚开始触摸屏幕的状态,将要下拉的状态
case EGOOPullRefreshNormal:
//如果为这个状态EGOOPullRefreshPulling则回归EGOOPullRefreshNormal状态
if (_state == EGOOPullRefreshPulling) {
[CATransaction begin];
[CATransaction setAnimationDuration:FLIP_ANIMATION_DURATION];
_arrowImage.transform = CATransform3DIdentity;
[CATransaction commit];
}
_statusLabel.text = NSLocalizedString(@"Pull down to refresh...", @"Pull down to refresh status");
[_activityView stopAnimating];
[CATransaction begin];
//因为下拉刷新完成好就不需要下拉动画,此时_activityView动画显示
//显示事物关闭动画效果 kCFBooleanTrue关闭 kCFBooleanFalse开启
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
_arrowImage.hidden = NO;
_arrowImage.transform = CATransform3DIdentity;
[CATransaction commit];
//更新时间
[self refreshLastUpdatedDate];
break;
//3.正在加载的状态
case EGOOPullRefreshLoading:
_statusLabel.text = NSLocalizedString(@"Loading...", @"Loading Status");
[_activityView startAnimating];
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
//正在加载的时候不需要箭头的显示所以直接隐藏
_arrowImage.hidden = YES;
[CATransaction commit];
break;
default:
break;
}
//把传进来的aState附值给全局
_state = aState;
}
#pragma mark -
#pragma mark ScrollView Methods
- (void)egoRefreshScrollViewDidScroll:(UIScrollView *)scrollView {
if (_state == EGOOPullRefreshLoading) {
CGFloat offset = MAX(scrollView.contentOffset.y * -1, 0);
offset = MIN(offset, 60);
scrollView.contentInset = UIEdgeInsetsMake(offset, 0.0f, 0.0f, 0.0f);
} else if (scrollView.isDragging) {
//2.如果scrollView正在被拖拽状态则_loading肯定为非
BOOL _loading = NO;
if ([_delegate respondsToSelector:@selector(egoRefreshTableHeaderDataSourceIsLoading:)]) {
_loading = [_delegate egoRefreshTableHeaderDataSourceIsLoading:self];
}
//如果_state处于EGOOPullRefreshPulling下拉的偏移量不满足则_state设置为EGOOPullRefreshNormal
if (_state == EGOOPullRefreshPulling && scrollView.contentOffset.y > -65.0f && scrollView.contentOffset.y < 0.0f && !_loading) {
[self setState:EGOOPullRefreshNormal];
//如果_state处于EGOOPullRefreshNormal下拉的偏移量不满足则_state设置为EGOOPullRefreshPulling
} else if (_state == EGOOPullRefreshNormal && scrollView.contentOffset.y < -65.0f && !_loading) {
[self setState:EGOOPullRefreshPulling];
}
//如果scrollView的上端偏移量不是0 设置为0
if (scrollView.contentInset.top != 0) {
scrollView.contentInset = UIEdgeInsetsZero;
}
}
}
- (void)egoRefreshScrollViewDidEndDragging:(UIScrollView *)scrollView {
BOOL _loading = NO;
if ([_delegate respondsToSelector:@selector(egoRefreshTableHeaderDataSourceIsLoading:)]) {
_loading = [_delegate egoRefreshTableHeaderDataSourceIsLoading:self];
}
if (scrollView.contentOffset.y <= - 65.0f && !_loading) {
if ([_delegate respondsToSelector:@selector(egoRefreshTableHeaderDidTriggerRefresh:)]) {
[_delegate egoRefreshTableHeaderDidTriggerRefresh:self];
}
[self setState:EGOOPullRefreshLoading];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
scrollView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f);
[UIView commitAnimations];
}
}
//完成数据加载回到原始的位置设置state为EGOOPullRefreshNormal
- (void)egoRefreshScrollViewDataSourceDidFinishedLoading:(UIScrollView *)scrollView {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
[scrollView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)];
[UIView commitAnimations];
[self setState:EGOOPullRefreshNormal];
}
#pragma mark -
#pragma mark Dealloc
- (void)dealloc {
_delegate=nil;
_activityView = nil;
_statusLabel = nil;
_arrowImage = nil;
_lastUpdatedLabel = nil;
[super dealloc];
}
@end