Initial commit

This commit is contained in:
ifish
2017-08-15 16:59:01 +08:00
commit bdc83e07ef
5766 changed files with 423223 additions and 0 deletions
BIN
View File
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
//
// JHRefreshAmazingAniView.h
// JHRefresh
//
// Created by Jiahai on 14-9-17.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshAniBaseView.h"
@interface JHRefreshAmazingAniView : JHRefreshAniBaseView
{
UIImageView *_aniImgView;
}
@end
+146
View File
@@ -0,0 +1,146 @@
//
// JHRefreshAmazingAniView.m
// JHRefresh
//
// Created by Jiahai on 14-9-17.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshAmazingAniView.h"
#import "JHRefreshMacro.h"
#import "UIView+JHExtension.h"
@implementation JHRefreshAmazingAniView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_aniImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:JHRefreshSrcName(@"JHdown_anim__0001.png")]];
_aniImgView.frame = CGRectMake(0, 0, 50, 50);
_aniImgView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
[self addSubview:_aniImgView];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
_aniImgView.center = CGPointMake(self.jh_width*0.5, self.jh_height*0.5);
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#pragma mark - JHRefreshViewDelegate
/**
* 下拉时的动画
*/
- (void)refreshViewAniToBePulling
{
}
/**
* 变成普通状态时的动画
*/
- (void)refreshViewAniToBeNormal
{
[_aniImgView stopAnimating];
}
/**
* 刷新开始
*/
- (void)refreshViewBeginRefreshing
{
if(!_aniImgView.animationImages)
{
// _aniImgView.animationImages = [NSArray arrayWithObjects:
// [UIImage imageNamed:JHRefreshSrcName(@"dropdown_loading_01.png")],
// [UIImage imageNamed:JHRefreshSrcName(@"dropdown_loading_02.png")],
//
// nil];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 1; i <= 63; i ++) {
if (i < 10) {
[images addObject:[UIImage imageNamed:[NSString stringWithFormat:@"neves000%d",i]]];
}else{
[images addObject:[UIImage imageNamed:[NSString stringWithFormat:@"neves00%d",i]]];
}
}
_aniImgView.animationImages=images;
_aniImgView.animationDuration = 2.0;
_aniImgView.animationRepeatCount = 0;
}
//刷新开始时,设置aniImageView的宽高
_aniImgView.jh_width = _aniImgView.jh_height = JHRefreshViewHeight;
[_aniImgView startAnimating];
}
/**
* 刷新结束
*
* @param result 刷新结果
*/
- (void)refreshViewEndRefreshing:(JHRefreshResult)result
{
}
/**
* 拖拽到对应的位置
*
* @param pos 位置,范围:1 ~ JHRefreshViewHeight
*/
- (void)refreshViewPullingToPosition:(NSInteger)pos
{
if(pos == 0)
{
return;
}
CGPoint center = _aniImgView.center;
_aniImgView.jh_width = _aniImgView.jh_height = pos;
_aniImgView.center = center;
NSString*name=nil;
name =@"neves0063.png";
//name = [NSString stringWithFormat:@"dropdown_anim__000%d.png",(int)pos];
// if (pos<10) {
// name = [NSString stringWithFormat:@"neves000%d.png",(int)pos];
// }else{
// name = [NSString stringWithFormat:@"neves00%d.png",(int)pos];
// }
//NSLog(@"pos%ld",(long)pos);
_aniImgView.image = [UIImage imageNamed:name];
}
@end
+17
View File
@@ -0,0 +1,17 @@
//
// JHRefreshAniBaseView.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JHRefreshViewDelegate.h"
#import "JHRefreshConfig.h"
@interface JHRefreshAniBaseView : UIView<JHRefreshViewDelegate>
@property (nonatomic, assign) JHRefreshViewType refreshViewType;
@property (nonatomic, assign) NSInteger refreshViewID;
@end
+74
View File
@@ -0,0 +1,74 @@
//
// JHRefreshAniBaseView.m
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshAniBaseView.h"
#import "JHRefreshHeaderView.h"
#import "JHRefreshFooterView.h"
#import "UIView+JHExtension.h"
@implementation JHRefreshAniBaseView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
self.jh_width = newSuperview.jh_width;
self.jh_height = newSuperview.jh_height;
if([newSuperview isKindOfClass:[JHRefreshHeaderView class]])
{
self.refreshViewType = JHRefreshViewTypeHeader;
}
else if([newSuperview isKindOfClass:[JHRefreshFooterView class]])
{
self.refreshViewType = JHRefreshViewTypeFooter;
}
self.refreshViewID = ((JHRefreshBaseView *)newSuperview).ID;
}
#pragma mark - JHRefreshViewDelegate
- (void)refreshViewAniToBePulling
{
}
- (void)refreshViewAniToBeNormal
{
}
- (void)refreshViewBeginRefreshing
{
}
- (void)refreshViewEndRefreshing:(JHRefreshResult)result
{
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
+21
View File
@@ -0,0 +1,21 @@
//
// JHRefreshCommonAniView.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JHRefreshMacro.h"
#import "JHRefreshAniBaseView.h"
@interface JHRefreshCommonAniView : JHRefreshAniBaseView
{
UIImageView *_arrowImgView;
UIImageView* _leftImgView;
UIActivityIndicatorView *_activityView;
UILabel *_statusLabel;
UILabel *_lastUpdateTimeLabel;
}
@end
+211
View File
@@ -0,0 +1,211 @@
//
// JHRefreshCommonAniView.m
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshCommonAniView.h"
#import "UIView+JHExtension.h"
#import "JHRefreshConfig.h"
#define ROT 3.14159265358979323846264338327950288
#define JHRefreshLabelTextColor JHRGBA(150,150,150,1)
@implementation JHRefreshCommonAniView
NSString *const JHRefreshHeaderStatusTextNormal = @"下拉刷新";
NSString *const JHRefreshHeaderStatusTextPulling = @"松开既可刷新";
NSString *const JHRefreshHeaderStatusTextRefreshing = @"正在刷新。。。";
NSString *const JHRefreshHeaderStatusTextSuccess = @"刷新成功";
NSString *const JHRefreshHeaderStatusTextFailure = @"刷新失败";
NSString *const JHRefreshFooterStatusTextNormal = @"上拉加载更多";
NSString *const JHRefreshFooterStatusTextPulling = @"松开既可加载";
NSString *const JHRefreshFooterStatusTextRefreshing = @"正在加载。。。";
NSString *const JHRefreshFooterStatusTextSuccess = @"加载成功";
NSString *const JHRefreshFooterStatusTextFailure = @"加载失败";
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_statusLabel = [[UILabel alloc] init];
_statusLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_statusLabel.font = [UIFont boldSystemFontOfSize:13];
_statusLabel.textColor = JHRefreshLabelTextColor;
_statusLabel.backgroundColor = [UIColor clearColor];
_statusLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_statusLabel];
_statusLabel.text = JHRefreshHeaderStatusTextNormal;
_lastUpdateTimeLabel = [[UILabel alloc] init];
_lastUpdateTimeLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_lastUpdateTimeLabel.font = [UIFont boldSystemFontOfSize:13];
_lastUpdateTimeLabel.textColor = JHRefreshLabelTextColor;
_lastUpdateTimeLabel.backgroundColor = [UIColor clearColor];
_lastUpdateTimeLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_lastUpdateTimeLabel];
_lastUpdateTimeLabel.text = [JHRefreshConfig getLastUpdateTimeWithRefreshViewID:self.refreshViewID];
// _arrowImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:JHRefreshSrcName(@"dropdown_loading_01")]];
_arrowImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@""]];
_arrowImgView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
[self addSubview:_arrowImgView];
// _leftImgView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:JHRefreshSrcName(@"dropdown_loading_01")]];
// _leftImgView.bounds=_arrowImgView.bounds;
// _leftImgView.autoresizingMask=_arrowImgView.autoresizingMask;
// [self addSubview:_leftImgView];
_activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
_activityView.bounds = _arrowImgView.bounds;
_activityView.autoresizingMask = _arrowImgView.autoresizingMask;
[self addSubview:_activityView];
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
if(self.refreshViewType == JHRefreshViewTypeFooter)
{
_statusLabel.text = JHRefreshFooterStatusTextNormal;
_arrowImgView.transform = CGAffineTransformMakeRotation(M_PI);
_lastUpdateTimeLabel.hidden = YES;
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
// 状态
_statusLabel.frame = CGRectMake(0, 0, self.jh_width, self.jh_height*0.5);
// 时间
_lastUpdateTimeLabel.frame = CGRectMake(0, _statusLabel.jh_height, _statusLabel.jh_width, _statusLabel.jh_height);
_arrowImgView.center = CGPointMake(self.jh_width*0.5 - 100, self.jh_height*0.5);
_activityView.center = _arrowImgView.center;
}
#pragma mark - JHRefreshViewDelegate
- (void)refreshViewAniToBePulling
{
switch (self.refreshViewType) {
case JHRefreshViewTypeHeader:
{
_statusLabel.text = JHRefreshHeaderStatusTextPulling;
[UIView animateWithDuration:JHRefreshFastAnimationDuration animations:^{
_arrowImgView.transform = CGAffineTransformMakeRotation(M_PI);
}];
}
break;
case JHRefreshViewTypeFooter:
{
_statusLabel.text = JHRefreshFooterStatusTextPulling;
[UIView animateWithDuration:JHRefreshFastAnimationDuration animations:^{
_arrowImgView.transform = CGAffineTransformIdentity;
}];
}
break;
}
}
- (void)refreshViewAniToBeNormal
{
switch (self.refreshViewType) {
case JHRefreshViewTypeHeader:
{
_statusLabel.text = JHRefreshHeaderStatusTextNormal;
[UIView animateWithDuration:JHRefreshFastAnimationDuration animations:^{
_arrowImgView.transform = CGAffineTransformIdentity;
}];
}
break;
case JHRefreshViewTypeFooter:
{
_statusLabel.text = JHRefreshFooterStatusTextNormal;
[UIView animateWithDuration:JHRefreshFastAnimationDuration animations:^{
_arrowImgView.transform = CGAffineTransformMakeRotation(2*ROT);
}];
}
break;
}
}
- (void)refreshViewBeginRefreshing
{
switch (self.refreshViewType) {
case JHRefreshViewTypeHeader:
{
_statusLabel.text = JHRefreshHeaderStatusTextRefreshing;
}
break;
case JHRefreshViewTypeFooter:
{
_statusLabel.text = JHRefreshFooterStatusTextRefreshing;
}
break;
}
_arrowImgView.hidden = YES;
[_activityView startAnimating];
}
- (void)refreshViewEndRefreshing:(JHRefreshResult)result
{
switch (self.refreshViewType) {
case JHRefreshViewTypeHeader:
{
switch (result) {
case JHRefreshResultNone:
_statusLabel.text = JHRefreshHeaderStatusTextNormal;
break;
case JHRefreshResultSuccess:
{
_statusLabel.text = JHRefreshHeaderStatusTextSuccess;
}
break;
case JHRefreshResultFailure:
{
_statusLabel.text = JHRefreshHeaderStatusTextFailure;
}
break;
}
_arrowImgView.transform = CGAffineTransformIdentity;
}
break;
case JHRefreshViewTypeFooter:
{
_statusLabel.text = JHRefreshHeaderStatusTextNormal;
_arrowImgView.transform = CGAffineTransformMakeRotation(M_PI);
}
break;
}
_lastUpdateTimeLabel.text = [JHRefreshConfig getLastUpdateTimeWithRefreshViewID:self.refreshViewID];
[JHRefreshConfig updateLastUpdateTimeWithRefreshViewID:self.refreshViewID];
[_activityView stopAnimating];
_arrowImgView.hidden = NO;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

+11
View File
@@ -0,0 +1,11 @@
//
// JHRefresh.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "UIScrollView+JHRefresh.h"
#import "JHRefreshCommonAniView.h"
#import "JHRefreshAmazingAniView.h"
+38
View File
@@ -0,0 +1,38 @@
//
// JHRefreshBaseView.h
// JHRefresh
//
// Created by Jiahai on 14-9-12.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JHRefreshAniBaseView.h"
typedef NS_ENUM(NSInteger, JHRefreshState) {
JHRefreshStatePulling = 1,
JHRefreshStateNormal,
JHRefreshStateRefreshing
};
@interface JHRefreshBaseView : UIView
/**
* App中有多个refreshView时,用以存放不同的配置信息,如:lastUpdateTime,也可不填
*/
@property (nonatomic, assign) NSInteger ID;
@property (nonatomic, weak, readonly) UIScrollView *scrollView;
@property (nonatomic, assign) JHRefreshState state;
@property (nonatomic, copy) void (^beginRefreshingBlock)();
@property (nonatomic, strong) JHRefreshAniBaseView<JHRefreshViewDelegate> *aniView;
//@property (nonatomic, copy) void (^)
@property (nonatomic, readonly) BOOL refreshing;
+ (instancetype)createView;
- (void)endRefreshingWithResult:(JHRefreshResult)result;
@end
+180
View File
@@ -0,0 +1,180 @@
//
// JHRefreshBaseView.m
// JHRefresh
//
// Created by Jiahai on 14-9-12.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshBaseView.h"
#import "JHRefreshConfig.h"
#import "UIScrollView+JHExtension.h"
#import "UIView+JHExtension.h"
@interface JHRefreshBaseView ()
@property (nonatomic, assign) JHRefreshResult refreshResult; //刷新是否成功
/**
* 正在刷新时设置contentInset的值,header设置Topfooter设置bottom
*/
- (void)setRefreshingContentInset;
/**
* 刷新完成后还原contentInset的值
*/
- (void)resumeContentInset;
@end
@implementation JHRefreshBaseView
+ (instancetype)createView
{
return [[[self class] alloc] init];
}
- (id)initWithFrame:(CGRect)frame
{
frame.size.height = JHRefreshViewHeight;
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.backgroundColor = [UIColor clearColor];
self.state = JHRefreshStateNormal;
}
return self;
}
- (void)setAniView:(JHRefreshAniBaseView<JHRefreshViewDelegate> *)aniView
{
if(_aniView)
{
[_aniView removeFromSuperview];
}
[self addSubview:aniView];
_aniView = aniView;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
self.jh_width = newSuperview.jh_width;
[self.superview removeObserver:self forKeyPath:JHRefreshContentOffset];
[newSuperview addObserver:self forKeyPath:JHRefreshContentOffset options:NSKeyValueObservingOptionNew context:nil];
_scrollView = (UIScrollView *)newSuperview;
}
- (BOOL)refreshing
{
return self.state == JHRefreshStateRefreshing;
}
- (void)setState:(JHRefreshState)state
{
//状态不改变什么都不做
if(_state == state)
return;
JHRefreshState oldState = _state;
_state = state;
switch (oldState) {
case JHRefreshStateNormal:
{
if(state == JHRefreshStatePulling)
{
//普通状态转为下拉状态
[_aniView refreshViewAniToBePulling];
}
}
break;
case JHRefreshStateRefreshing:
{
if(state == JHRefreshStateNormal)
{
//刷新状态转为普通状态
[_aniView refreshViewEndRefreshing:_refreshResult];
switch (_refreshResult) {
case JHRefreshResultNone:
{
[self resumeContentInset];
[_aniView refreshViewAniToBeNormal];
}
break;
case JHRefreshResultSuccess:
case JHRefreshResultFailure:
{
//展示刷新结果,延时隐藏refreshView;
dispatch_time_t delayInNanoSeconds =dispatch_time(DISPATCH_TIME_NOW, JHRefreshShowResultAnimationDuration * NSEC_PER_SEC);
//延期执行
dispatch_after(delayInNanoSeconds, dispatch_get_main_queue(), ^{
[UIView animateWithDuration:JHRefreshSlowAnimationDuration animations:^{
[self resumeContentInset];
[_aniView refreshViewAniToBeNormal];
}];
});
}
break;
}
}
}
break;
case JHRefreshStatePulling:
{
if(state == JHRefreshStateNormal)
{
//下拉状态转为普通状态
[_aniView refreshViewAniToBeNormal];
}
else if(state == JHRefreshStateRefreshing)
{
//下拉状态转为刷新状态
//
[self setRefreshingContentInset];
[_aniView refreshViewBeginRefreshing];
//执行刷新block
if(self.beginRefreshingBlock)
self.beginRefreshingBlock();
}
}
break;
}
}
- (void)endRefreshingWithResult:(JHRefreshResult)result
{
self.refreshResult = result;
self.state = JHRefreshStateNormal;
}
- (void)setRefreshingContentInset
{
}
- (void)resumeContentInset
{
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
+53
View File
@@ -0,0 +1,53 @@
//
// JHRefreshConfig.h
// JHRefresh
//
// Created by Jiahai on 14-9-12.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "JHRefreshMacro.h"
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, JHRefreshViewType) {
JHRefreshViewTypeHeader = 1,
JHRefreshViewTypeFooter
};
/**
* 刷新结果
*/
typedef NS_ENUM(NSInteger, JHRefreshResult) {
/**
* 不展示刷新结果,刷新结束直接隐藏
*/
JHRefreshResultNone = 0,
/**
* 展示刷新成功界面,延时隐藏
*/
JHRefreshResultSuccess,
/**
* 展示刷新失败界面,延时隐藏
*/
JHRefreshResultFailure
};
extern const CGFloat JHRefreshViewHeight;
extern const CGFloat JHRefreshFastAnimationDuration;
extern const CGFloat JHRefreshSlowAnimationDuration;
extern const CGFloat JHRefreshShowResultAnimationDuration;
extern NSString *const JHRefreshContentOffset;
extern NSString *const JHRefreshContentSize;
@interface JHRefreshConfig : NSObject
+ (NSString *)getLastUpdateTimeWithRefreshViewID:(NSInteger)ID;
+ (void)updateLastUpdateTimeWithRefreshViewID:(NSInteger)ID;
@end
+75
View File
@@ -0,0 +1,75 @@
//
// JHRefreshConfig.m
// JHRefresh
//
// Created by Jiahai on 14-9-12.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshConfig.h"
const CGFloat JHRefreshViewHeight = 63.0;
const CGFloat JHRefreshFastAnimationDuration = 0.2;
const CGFloat JHRefreshSlowAnimationDuration = 0.4;
const CGFloat JHRefreshShowResultAnimationDuration = 0.5;
NSString *const JHRefreshContentOffset = @"contentOffset";
NSString *const JHRefreshContentSize = @"contentSize";
NSString *const JHRefreshConfigKey = @"JHRefreshConfig";
NSString *const JHRefreshLastUpdateTimeKey = @"JHRefreshLastUpdateTime";
NSString *const JHRefreshLastUpdateTimeFormat = @"yyyy-MM-dd HH:mm";
/**
* JHRefreshConfig的目录结构
--NSUserDefaults
|
——JHRefreshConfigKey //JHRefresh所有的配置存储路径
|
|——JHRefreshLastUpdateTimeKey //lastUpdateTime配置存储路径
*/
@implementation JHRefreshConfig
+ (NSString*)nowTimeString
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:JHRefreshLastUpdateTimeFormat];
return [NSString stringWithFormat:@"上次刷新:%@", [dateFormatter stringFromDate:[NSDate date]]];
}
+ (NSString *)getLastUpdateTimeWithRefreshViewID:(NSInteger)ID
{
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSDictionary *refreshDic = [userDefault objectForKey:JHRefreshConfigKey];
NSString *time = [[refreshDic objectForKey:JHRefreshLastUpdateTimeKey] objectForKey:[NSString stringWithFormat:@"%@_%d",JHRefreshLastUpdateTimeKey,ID]];
if(!time)
{
return [[self class] nowTimeString];
}
return time;
}
+ (void)updateLastUpdateTimeWithRefreshViewID:(NSInteger)ID
{
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *refreshDic = [userDefault objectForKey:JHRefreshConfigKey];
if(!refreshDic)
{
refreshDic = [NSMutableDictionary dictionary];
}
NSMutableDictionary *lastUpdateTimeDic = [refreshDic objectForKey:JHRefreshLastUpdateTimeKey];
if(!lastUpdateTimeDic)
{
lastUpdateTimeDic = [NSMutableDictionary dictionary];
}
[lastUpdateTimeDic setObject:[[self class] nowTimeString] forKey:[NSString stringWithFormat:@"%@_%d",JHRefreshLastUpdateTimeKey,ID]];
[userDefault setObject:refreshDic forKey:JHRefreshConfigKey];
[userDefault synchronize];
}
@end
+13
View File
@@ -0,0 +1,13 @@
//
// JHRefreshFooterView.h
// JHRefresh
//
// Created by Jiahai on 14-9-16.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshBaseView.h"
@interface JHRefreshFooterView : JHRefreshBaseView
@end
+128
View File
@@ -0,0 +1,128 @@
//
// JHRefreshFooterView.m
// JHRefresh
//
// Created by Jiahai on 14-9-16.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshFooterView.h"
#import "JHRefreshConfig.h"
#import "UIView+JHExtension.h"
#import "UIScrollView+JHExtension.h"
@implementation JHRefreshFooterView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
[self.superview removeObserver:self forKeyPath:JHRefreshContentSize];
[newSuperview addObserver:self forKeyPath:JHRefreshContentSize options:NSKeyValueObservingOptionNew context:nil];
[self ajustFooterView];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:JHRefreshContentSize])
{
[self ajustFooterView];
}
//正在刷新,直接返回
if(self.state == JHRefreshStateRefreshing)
{
return;
}
if([keyPath isEqualToString:JHRefreshContentOffset])
{
[self changeStateWithContentOffset];
if([self.aniView respondsToSelector:@selector(refreshViewPullingToPosition:)])
{
NSInteger pos = self.scrollView.contentOffset.y + self.scrollView.jh_height - self.scrollView.jh_contentSizeHeight-self.scrollView.jh_contentInsetBottom;
//footerView不可见/全部显示后,直接返回
if(pos <= 0 || pos > JHRefreshViewHeight)
return;
[self.aniView refreshViewPullingToPosition:pos];
}
}
}
- (void)changeStateWithContentOffset
{
CGFloat currentOffsetY = self.scrollView.contentOffset.y;
CGFloat releaseToRefreshOffsetY = MAX(self.scrollView.jh_contentSizeHeight,self.scrollView.jh_height) - self.scrollView.jh_height + self.scrollView.jh_contentInsetBottom;
//footerView的顶端不可见时,直接返回
if(currentOffsetY <= releaseToRefreshOffsetY)
{
return;
}
releaseToRefreshOffsetY += JHRefreshViewHeight;
if(self.scrollView.isDragging)
{
if(self.state == JHRefreshStateNormal && currentOffsetY>releaseToRefreshOffsetY)
{
self.state = JHRefreshStatePulling;
}
else if(self.state == JHRefreshStatePulling && currentOffsetY <= releaseToRefreshOffsetY)
{
self.state = JHRefreshStateNormal;
}
}
else
{
if(self.state == JHRefreshStatePulling)
{
self.state = JHRefreshStateRefreshing;
}
}
}
/**
* 调整footerView的位置
*/
- (void)ajustFooterView
{
CGFloat contentSizeHeight = self.scrollView.jh_contentSizeHeight;
CGFloat height = self.scrollView.jh_height;
self.jh_originY = MAX(height, contentSizeHeight);
}
- (void)setRefreshingContentInset
{
self.scrollView.jh_contentInsetBottom += JHRefreshViewHeight;
}
- (void)resumeContentInset
{
self.scrollView.jh_contentInsetBottom -= JHRefreshViewHeight;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
+13
View File
@@ -0,0 +1,13 @@
//
// JHRefreshHeaderView.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshBaseView.h"
@interface JHRefreshHeaderView : JHRefreshBaseView
@end
+105
View File
@@ -0,0 +1,105 @@
//
// JHRefreshHeaderView.m
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "JHRefreshHeaderView.h"
#import "JHRefreshConfig.h"
#import "UIScrollView+JHExtension.h"
#import "UIView+JHExtension.h"
@implementation JHRefreshHeaderView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
self.jh_originY = -JHRefreshViewHeight;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if(self.state == JHRefreshStateRefreshing)
return;
if([keyPath isEqualToString:JHRefreshContentOffset])
{
[self changeStateWithContentOffset];
if([self.aniView respondsToSelector:@selector(refreshViewPullingToPosition:)])
{
NSInteger pos = self.scrollView.contentOffset.y;
//headerView不可见/全部可见时,直接返回
if(pos > 0 || pos < -JHRefreshViewHeight-self.scrollView.jh_contentInsetTop)
return;
[self.aniView refreshViewPullingToPosition:abs((int)pos)-self.scrollView.jh_contentInsetTop];
}
}
}
- (void)changeStateWithContentOffset
{
CGFloat currentOffsetY = self.scrollView.contentOffset.y;
CGFloat releaseToRefreshOffsetY = - self.scrollView.jh_contentInsetTop;
//headerView的顶端不可见时,直接返回
if(currentOffsetY>=releaseToRefreshOffsetY)
return;
releaseToRefreshOffsetY -= self.jh_height;
if(self.scrollView.isDragging)
{
if(self.state == JHRefreshStateNormal && currentOffsetY < releaseToRefreshOffsetY)
{
//即将刷新
self.state = JHRefreshStatePulling;
}
else if(self.state == JHRefreshStatePulling && currentOffsetY>=releaseToRefreshOffsetY)
{
//普通状态
self.state = JHRefreshStateNormal;
}
}
else if (self.state == JHRefreshStatePulling)
{
//开始刷新
self.state = JHRefreshStateRefreshing;
}
}
- (void)setRefreshingContentInset
{
self.scrollView.jh_contentInsetTop += JHRefreshViewHeight;
}
- (void)resumeContentInset
{
self.scrollView.jh_contentInsetTop -= JHRefreshViewHeight;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
+27
View File
@@ -0,0 +1,27 @@
//
// JHRefreshMacro.h
// JHRefresh
//
// Created by Jiahai on 14-9-12.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#ifndef JHRefresh_JHRefreshMacro_h
#define JHRefresh_JHRefreshMacro_h
#pragma mark - 通用
#ifdef DEBUG
#define JHLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define JHLog(fmt, ...)
#endif
#define JHRefreshBundleName @"JHRefresh.bundle"
#define JHRefreshSrcName(file) ([JHRefreshBundleName stringByAppendingPathComponent:(file)])
#pragma mark 颜色配置
#define JHRGBA(r,g,b,a) [UIColor colorWithRed:(float)r/255.0f green:(float)g/255.0f blue:(float)b/255.0f alpha:a]
#endif
+42
View File
@@ -0,0 +1,42 @@
//
// JHRefreshViewDelegate.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "JHRefreshConfig.h"
@protocol JHRefreshViewDelegate <NSObject>
@required
/**
* 下拉时的动画
*/
- (void)refreshViewAniToBePulling;
/**
* 变成普通状态时的动画
*/
- (void)refreshViewAniToBeNormal;
/**
* 刷新开始
*/
- (void)refreshViewBeginRefreshing;
/**
* 刷新结束
*
* @param result 刷新结果
*/
- (void)refreshViewEndRefreshing:(JHRefreshResult)result;
@optional
/**
* 拖拽到对应的位置
*
* @param pos 位置,范围:1-JHRefreshViewHeight
*/
- (void)refreshViewPullingToPosition:(NSInteger)pos;
@end
+20
View File
@@ -0,0 +1,20 @@
//
// UIScrollView+JHExtension.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIScrollView (JHExtension)
@property (nonatomic, assign) CGFloat jh_contentInsetTop;
@property (nonatomic, assign) CGFloat jh_contentInsetBottom;
@property (nonatomic, assign) CGFloat jh_contentInsetLeft;
@property (nonatomic, assign) CGFloat jh_contentInsetRight;
@property (nonatomic, assign) CGFloat jh_contentSizeWidth;
@property (nonatomic, assign) CGFloat jh_contentSizeHeight;
@end
+75
View File
@@ -0,0 +1,75 @@
//
// UIScrollView+JHExtension.m
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "UIScrollView+JHExtension.h"
@implementation UIScrollView (JHExtension)
#pragma mark - contentInset
- (CGFloat)jh_contentInsetTop
{
return self.contentInset.top;
}
- (void)setJh_contentInsetTop:(CGFloat)jh_contentInsetTop
{
UIEdgeInsets inset = self.contentInset;
inset.top = jh_contentInsetTop;
self.contentInset = inset;
}
- (CGFloat)jh_contentInsetBottom
{
return self.contentInset.bottom;
}
- (void)setJh_contentInsetBottom:(CGFloat)jh_contentInsetBottom
{
UIEdgeInsets inset = self.contentInset;
inset.bottom = jh_contentInsetBottom;
self.contentInset = inset;
}
- (CGFloat)jh_contentInsetLeft
{
return self.contentInset.left;
}
- (void)setJh_contentInsetLeft:(CGFloat)jh_contentInsetLeft
{
UIEdgeInsets inset = self.contentInset;
inset.left = jh_contentInsetLeft;
self.contentInset = inset;
}
- (CGFloat)jh_contentInsetRight
{
return self.contentInset.right;
}
- (void)setJh_contentInsetRight:(CGFloat)jh_contentInsetRight
{
UIEdgeInsets inset = self.contentInset;
inset.right = jh_contentInsetRight;
self.contentInset = inset;
}
#pragma mark - contentSize
- (CGFloat)jh_contentSizeWidth
{
return self.contentSize.width;
}
- (void)setJh_contentSizeWidth:(CGFloat)jh_contentSizeWidth
{
CGSize size = self.contentSize;
size.width = jh_contentSizeWidth;
self.contentSize = size;
}
- (CGFloat)jh_contentSizeHeight
{
return self.contentSize.height;
}
- (void)setJh_contentSizeHeight:(CGFloat)jh_contentSizeHeight
{
CGSize size = self.contentSize;
size.height = jh_contentSizeHeight;
self.contentSize = size;
}
@end
+44
View File
@@ -0,0 +1,44 @@
//
// UIScrollView+JHRefresh.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JHRefreshConfig.h"
@interface UIScrollView (JHRefresh)
/**
* 添加下拉刷新HeaderView
*
* @param aniViewClass 需要执行的动画的Class
* @param beginRefresh 开始刷新时需要执行的操作,如网络请求等
*/
- (void)addRefreshHeaderViewWithAniViewClass:(Class)aniViewClass beginRefresh:(void (^)())beginRefresh;
/**
* 添加上拉加载FooterView
*
* @param aniViewClass 需要执行的动画的Class
* @param beginRefresh 开始刷新时需要执行的操作,如网络请求等
*/
- (void)addRefreshFooterViewWithAniViewClass:(Class)aniViewClass beginRefresh:(void (^)())beginRefresh;
/**
* 自动开启下拉刷新
*/
- (void)headerStartRefresh;
/**
* 结束下拉刷新
*
* @param result 刷新结果
*/
- (void)headerEndRefreshingWithResult:(JHRefreshResult)result;
/**
* 结束上拉加载
*/
- (void)footerEndRefreshing;
@end
+95
View File
@@ -0,0 +1,95 @@
//
// UIScrollView+JHRefresh.m
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "UIScrollView+JHRefresh.h"
#import "JHRefreshHeaderView.h"
#import "JHRefreshFooterView.h"
#import "AnimationView/JHRefreshCommonAniView.h"
#import "AnimationView/JHRefreshAmazingAniView.h"
#import "objc/runtime.h"
@interface UIScrollView()
@property (nonatomic, weak) JHRefreshHeaderView *header;
@property (nonatomic, weak) JHRefreshFooterView *footer;
@end
@implementation UIScrollView (JHRefresh)
#pragma mark - 关联属性
static char JHRefreshHeaderViewKey;
static char JHRefreshFooterViewKey;
- (void)setHeader:(JHRefreshHeaderView *)header {
[self willChangeValueForKey:@"JHRefreshHeaderViewKey"];
objc_setAssociatedObject(self, &JHRefreshHeaderViewKey,
header,
OBJC_ASSOCIATION_ASSIGN);
[self didChangeValueForKey:@"JHRefreshHeaderViewKey"];
}
- (JHRefreshHeaderView *)header {
return objc_getAssociatedObject(self, &JHRefreshHeaderViewKey);
}
- (void)setFooter:(JHRefreshFooterView *)footer {
[self willChangeValueForKey:@"JHRefreshFooterViewKey"];
objc_setAssociatedObject(self, &JHRefreshFooterViewKey,
footer,
OBJC_ASSOCIATION_ASSIGN);
[self didChangeValueForKey:@"JHRefreshFooterViewKey"];
}
- (JHRefreshFooterView *)footer {
return objc_getAssociatedObject(self, &JHRefreshFooterViewKey);
}
#pragma mark -
- (void)addRefreshHeaderViewWithAniViewClass:(Class)aniViewClass beginRefresh:(void (^)())beginRefresh
{
assert([aniViewClass isSubclassOfClass:[JHRefreshAniBaseView class]]);
if(!self.header)
{
JHRefreshHeaderView *headerView = [JHRefreshHeaderView createView];
headerView.beginRefreshingBlock = beginRefresh;
[self addSubview:headerView];
self.header = headerView;
headerView.aniView = [[aniViewClass alloc] init];
}
}
- (void)addRefreshFooterViewWithAniViewClass:(Class)aniViewClass beginRefresh:(void (^)())beginRefresh
{
assert([aniViewClass isSubclassOfClass:[JHRefreshAniBaseView class]]);
if(!self.footer)
{
JHRefreshFooterView *footerView = [JHRefreshFooterView createView];
footerView.beginRefreshingBlock = beginRefresh;
[self addSubview:footerView];
self.footer = footerView;
footerView.aniView = [[aniViewClass alloc] init];
}
}
- (void)headerStartRefresh
{
self.header.state = JHRefreshStatePulling;
self.contentOffset = CGPointMake(self.contentOffset.x, -JHRefreshViewHeight);
}
- (void)headerEndRefreshingWithResult:(JHRefreshResult)result
{
[self.header endRefreshingWithResult:result];
}
- (void)footerEndRefreshing
{
[self.footer endRefreshingWithResult:JHRefreshResultNone];
}
@end
+18
View File
@@ -0,0 +1,18 @@
//
// UIView+JHExtension.h
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (JHExtension)
@property (nonatomic, assign) CGFloat jh_originX;
@property (nonatomic, assign) CGFloat jh_originY;
@property (nonatomic, assign) CGFloat jh_width;
@property (nonatomic, assign) CGFloat jh_height;
@end
+56
View File
@@ -0,0 +1,56 @@
//
// UIView+JHExtension.m
// JHRefresh
//
// Created by Jiahai on 14-9-15.
// Copyright (c) 2014年 Jiahai. All rights reserved.
//
#import "UIView+JHExtension.h"
@implementation UIView (JHExtension)
- (CGFloat)jh_originX
{
return self.frame.origin.x;
}
- (void)setJh_originX:(CGFloat)jh_originX
{
CGRect rect = self.frame;
rect.origin.x = jh_originX;
self.frame = rect;
}
- (CGFloat)jh_originY
{
return self.frame.origin.y;
}
- (void)setJh_originY:(CGFloat)jh_originY
{
CGRect rect = self.frame;
rect.origin.y = jh_originY;
self.frame = rect;
}
- (CGFloat)jh_width
{
return self.frame.size.width;
}
- (void)setJh_width:(CGFloat)jh_width
{
CGRect rect = self.frame;
rect.size.width = jh_width;
self.frame = rect;
}
- (CGFloat)jh_height
{
return self.frame.size.height;
}
- (void)setJh_height:(CGFloat)jh_height
{
CGRect rect = self.frame;
rect.size.height = jh_height;
self.frame = rect;
}
@end