【无线互联】EGORefreshTableHeaderView下拉刷新 原理

    IOS中,经常会使用到下拉刷新UITableView中的数据,比如新浪的客户端,我们就是使用下拉刷新方式来更新微博数据。所以这次主要是对EGORefreshTableHeaderView下拉刷新原理进行分析。

    在EGORefreshTableHeaderView中只支持英文,通过修改文中_statusLabel.text的内容,可以支持这种那个英文,例如_statusLabel.text = NSLocalizedString(@"下拉刷新",@"Release to refresh status"); 

    UITableView继承于UIScrollView,所以可以使用UIScrollView中y的位移量contentOffset.y 计算用户当前下拉的位置,从而判断是否开始刷新数据。

    首先在TableView视图中,我们首先给视图添加一个view用来显示下拉刷新的状态,我们可以把它叫做refreshHeardView。在普通状态下,我们看不到refreshHeardView,因此我们可以将其frame设置到屏幕以外;当用户下拉列表时refreshHeardView就会一点一点显示出来。

    普通状态下,contentOffset.y = 0;当用户下拉时,contentOffsetu6.y的值不断变小refreshHeardView上显示的箭头朝下,内容为:下拉加载.......;contentOffset.y <= -65 -offsetY(#define offsetY (refresh_ios7?64.0:0.0))时,refreshHeardView上控件就会完全显示出来,此时箭头朝上,变为:加载新微博; 此时放手,refreshHeardView不上内容变为:正在加载...........;效果图如 下图所示


            

    根据上面原理就不难理解下面代码中的原理 :

    首先是在初始化的时候创建我们所需要的视图view中的各个控件。_lastUpdateLabel用来显示时间;_statusLabel用来显示下拉的状态;_arrowImage用来显示箭头;_activityView是指示等待器,当加载数据是显示。

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
		
		self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
		self.backgroundColor = [UIColor colorWithRed:226.0/255.0 green:231.0/255.0 blue:237.0/255.0 alpha:1.0];

		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 = NSTextAlignmentCenter;
		[self addSubview:label];
		_lastUpdatedLabel=label;
		[label release];
		
		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 = NSTextAlignmentCenter;
		[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.contentsGravity = kCAGravityResizeAspect;
		layer.contents = (id)[UIImage imageNamed:@"blueArrow.png"].CGImage;
		
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
		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];
		
		
		[self setState:EGOOPullRefreshNormal];
		
    }
	
    return self;
	
}
    下面代码用来显示最后的更新时间

- (void)refreshLastUpdatedDate {
	
	if ([_delegate respondsToSelector:@selector(egoRefreshTableHeaderDataSourceLastUpdated:)]) {
		
		NSDate *date = [_delegate egoRefreshTableHeaderDataSourceLastUpdated:self];
		
		NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
		[formatter setAMSymbol:@"AM"];
		[formatter setPMSymbol:@"PM"];
		[formatter setDateFormat:@"MM/dd/yyyy hh:mm:a"];
		_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;
		
	}

}

    然后是设置当前视图的状态;首先在.h文件中定义一个枚举
typedef enum{
	EGOOPullRefreshPulling = 0,
	EGOOPullRefreshNormal,
	EGOOPullRefreshLoading,	
} EGOPullRefreshState;
    并且定义个状态属性——state并给设置一个set方法,初始化时_state=EGOOPullRefreshNormal。当_state的值变换时,视图中各个控件也相应地变换,
- (void)setState:(EGOPullRefreshState)aState{
	
	switch (aState) {
		case EGOOPullRefreshPulling:
			
			_statusLabel.text = NSLocalizedString(@"加载新微博...", @"Release to refresh status");
			[CATransaction begin];
			[CATransaction setAnimationDuration:4];
//			_arrowImage.transform = CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.0f);
            _arrowImage.transform = CATransform3DMakeRotation(M_PI ,1.0f, 0.0f, 0.0f);
			[CATransaction commit];
			
			break;
		case EGOOPullRefreshNormal:
			
			if (_state == EGOOPullRefreshPulling) {
				[CATransaction begin];
				[CATransaction setAnimationDuration:FLIP_ANIMATION_DURATION];
				_arrowImage.transform = CATransform3DIdentity;
				[CATransaction commit];
			}
			
			_statusLabel.text = NSLocalizedString(@"下拉加载...", @"Pull down to refresh status");
			[_activityView stopAnimating];
			[CATransaction begin];
			[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 
			_arrowImage.hidden = NO;
			_arrowImage.transform = CATransform3DIdentity;
			[CATransaction commit];
			
			[self refreshLastUpdatedDate];
			
			break;
		case EGOOPullRefreshLoading:
			
			_statusLabel.text = NSLocalizedString(@"正在加载...", @"Loading Status");
			[_activityView startAnimating];
			[CATransaction begin];
			[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 
			_arrowImage.hidden = YES;
			[CATransaction commit];
			
			break;
		default:
			break;
	}
	
	_state = aState;
}
   然后在.h中定义一个一个判断是佛正在加载的属性_loading 和3个方法

- (void)egoRefreshScrollViewDidScroll:(UIScrollView *)scrollView;

- (void)egoRefreshScrollViewDidEndDragging:(UIScrollView *)scrollView;

- (void)egoRefreshScrollViewDataSourceDidFinishedLoading:(UIScrollView *)scrollView;

   当用户刚开始滑动调用第一个方法,将_loading设置为no;此时处于视图为“下拉加载”状态;此时用户滑动位移值contentOffset.y大于-65-offsetY小于0;当contentOffset.y<-65-offsetY时_state由EGOOPullRefreshNormal变为EGOOPullRefreshPulling;此时视图为“加载新微博”;但两种状态只有在_loading为NO时互相转换,因为处于加载时视图是不能变化的;当ontentOffset.y<-65-offsetY并停止拖拽时调用第二个方法,将_statue的值变为EGOOPullRefreshLoading;此时处于加载状态,为了防止在加载时滑动影响加载状态,可以用_loading 约束,当_loading 为YES时以上操作都不能执行;因为加载的完成不能由该类中控制,所以_loading指的设置和获取可以通过

设置代理来实现,因此在.h设置了一个代理。

@protocol EGORefreshTableHeaderDelegate
//- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view;
//- (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView*)view;
@optional
- (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView*)view;
  当加载结束后用户调用第三个方法,让_statu变  EGOOPullRefreshNormal,tableview也变为初始状态。这样下拉刷新就实现就完成了。
- (void)egoRefreshScrollViewDataSourceDidFinishedLoading:(UIScrollView *)scrollView {	
	
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:.3];
	[scrollView setContentInset:UIEdgeInsetsMake(offsetY, 0.0f, 0.0f, 0.0f)];
	[UIView commitAnimations];
	
	[self setState:EGOOPullRefreshNormal];

}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值