【无限互 联】下拉刷新EGORefreshTableHeaderView的使用

下载开源框架的地址:https://github.com/enormego/EGOTableViewPullRefresh

一,为什么使用EGORefreshTableHeaderView框架

       应用中如果要展示大量数据列表,肯定不会一次都加载进来的,常规的方法都是从服务器翻页请求,每次请求n条,用户选择加载更多的时候再请求n条,如果使用下拉刷新的话就会方便很多,用户体验也会好。现在下拉刷新应该很多人都采用了EGORefreshTableHeaderView,具体的UI效果当然会根据自己产品的设计,再进行修改。

      例如:QQ空间客户端,新浪微博客服端,我们就是使用下拉刷新方式来更新空间数据。所以这次主要是对EGORefreshTableHeaderView下拉刷新原理进行分析。

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

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

      普通状态下,contentOffset.y = 0;当用户下拉时,contentOffset.y的值不断变小refreshHeardView上显示的箭头朝下,内容为:下拉加载.......;contentOffset.y <= -65 -offset.Y,refreshHeardView上拉控件就会完全显示出来,此时箭头朝上,变为:加载QQ空间; 此时放手,refreshHeardView上内容变为:正在加载...........;效果图如 下图所示



              


二,EGORefreshTableHeaderView的原理

下面在根据代码将解他的原理 :

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


- (id)initWithFrame:(CGRect)frame {

    if (self = [superinitWithFrame:frame]) 

{

        //自动调整自己的宽度,保证与superView左边和右边的距离不变。

self.autoresizingMask =UIViewAutoresizingFlexibleWidth;

self.backgroundColor = [UIColorcolorWithRed:226.0/255.0                              green:231.0/255.0 blue:237.0/255.0 alpha:1.0];


        //这是最后刷新时间的label

UILabel *label = [[UILabelalloc]initWithFrame:CGRectMake(0.0f,                       frame.size.height - 30.0f,self.frame.size.width, 20.0f)];

label.autoresizingMask =UIViewAutoresizingFlexibleWidth;

label.font = [UIFontsystemFontOfSize:12.0f];

label.textColor =TEXT_COLOR;

                label.backgroundColor = [UIColorclearColor];

                label.textAlignment =NSTextAlignmentCenter;

[self addSubview:label];

_lastUpdatedLabel=label;

[label release];

        //这里是显示状态的label

label = [[UILabelalloc]initWithFrame:CGRectMake(0.0f,                               frame.size.height - 48.0f,self.frame.size.width, 20.0f)];

label.autoresizingMask =UIViewAutoresizingFlexibleWidth;

label.font = [UIFontboldSystemFontOfSize:13.0f];

label.textColor =TEXT_COLOR;

                label.backgroundColor = [UIColorclearColor];

                label.textAlignment =NSTextAlignmentCenter;

[self addSubview:label];

_statusLabel=label;

[label release];

        //创建下拉刷新的图标

CALayer *layer = [CALayerlayer];

layer.frame =CGRectMake(25.0f, frame.size.height - 65.0f, 30.0f,                     55.0f);

        

        //设置layerview上以某种形式适应

layer.contentsGravity =kCAGravityResizeAspect;

layer.contents = (id)[UIImageimageNamed:@"blackArrow.png"].CGImage;

        //这里是判断系统版本,来设置layer的属性

                #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000//条件编译

if ([[UIScreenmainScreen]respondsToSelector:@selector(scale)]) {

layer.contentsScale = [[UIScreenmainScreen]scale];

}

                #endif

[[selflayer]addSublayer:layer];

_arrowImage=layer;

//创建一个旋转的视图

UIActivityIndicatorView *view = [[UIActivityIndicatorViewalloc]                       initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];

view.frame =CGRectMake(25.0f, frame.size.height - 38.0f, 20.0f,                       20.0f);

[self addSubview:view];

_activityView = view;

[view release];

//UI弄完后设置纬初始状态

[selfsetState:EGOOPullRefreshNormal];

                }

    return self;

}





2.下面代码用来显示最后的更新时间


- (void)refreshLastUpdatedDate {

if ([_delegate                                            respondsToSelector:@selector(egoRefreshTableHeaderDataSourceLastUpdated:)]) {

NSDate *date = [_delegate          egoRefreshTableHeaderDataSourceLastUpdated:self];

        /*,相应的NSDateFormatter就相当于是NSDate的转换类,将NSDate转换为另一种格式,或转换回来。NSDate没有自己的输出,需要借助NSDateFormatter以相应格式输出。这差不多就是NSDateFormatter的作用了吧。*/

        

        

           //实例化一个对象

               //      NSDateFormatter实例创建字符串,来表示NSDateNSCalendarDate对象,已预  订格式化字符串输出

NSDateFormatter *formatter = [[NSDateFormatteralloc]init];

[formattersetAMSymbol:@"AM"];

[formattersetPMSymbol:@"PM"];

        

        //设置时间的格式

[formatter setDateFormat:@"MM/dd/yyyy HH:mm"];

_lastUpdatedLabel.text = [NSStringstringWithFormat:@"上次刷新: %@",                     [formatter stringFromDate:date]];

        //存储_lastUpdatedLabel.text内容,放到字典中

[[NSUserDefaultsstandardUserDefaults]                   setObject:_lastUpdatedLabel.textforKey:@"EGORefreshTableView_LastRefresh"];

        //NSUserDefaults存储数据放到磁盘

[[NSUserDefaultsstandardUserDefaults]synchronize];

[formatterrelease];

}else {

_lastUpdatedLabel.text =nil;

}


}



3. 然后是设置当前视图的状态;首先在.h文件中定义一个枚举

typedef enum{

    //松开即可刷新

EGOOPullRefreshPulling = 0,

    //下拉即可刷新

EGOOPullRefreshNormal,

    //载入中

EGOOPullRefreshLoading,

} EGOPullRefreshState;



4.并且定义个状态属性——state并给设置一个set方法,初始化时_state=EGOOPullRefreshNormal。当_state的值变换时,视图中各个控件也相应地变换,


- (void)setState:(EGOPullRefreshState)aState{

switch (aState) {

            /*触摸屏幕下拉状态*/

caseEGOOPullRefreshPulling:

_statusLabel.text =NSLocalizedString(@"松开即可刷新...",@"Release to refresh status");

            

            //设置下拉刷新过程,箭头的图片的一个动画过程

[CATransactionbegin];

            //动画时间

[CATransactionsetAnimationDuration:FLIP_ANIMATION_DURATION];

            //下拉刷新箭头一个翻转过程,(M_PI / 180.0)是角度转换为弧度

_arrowImage.transform =CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.0f);

            //动画结束

[CATransactioncommit];

break;

            /*刚开始触摸屏幕准备下拉的时候的状态*/

caseEGOOPullRefreshNormal:

if (_state ==EGOOPullRefreshPulling) {

[CATransactionbegin];

                //因为下拉刷新完成好就不需要下拉动画,此时_activityView动画显示

                //显示事物关闭动画效果 kCFBooleanTrue关闭 kCFBooleanFalse开启

[CATransactionsetAnimationDuration:FLIP_ANIMATION_DURATION];

_arrowImage.transform =CATransform3DIdentity;

[CATransactioncommit];

}

_statusLabel.text =NSLocalizedString(@"下拉可以刷新...",@"Pull down to refresh status");

[_activityViewstopAnimating];

[CATransactionbegin];

[CATransactionsetValue:(id)kCFBooleanTrueforKey:kCATransactionDisableActions]; 

_arrowImage.hidden =NO;

_arrowImage.transform =CATransform3DIdentity;

[CATransactioncommit];

//更新下时间

[selfrefreshLastUpdatedDate];

break;

            /*触摸手指松开,完成下拉操作的状态*/

caseEGOOPullRefreshLoading:

_statusLabel.text =NSLocalizedString(@"载入中...",@"Loading Status");

[_activityViewstartAnimating];

[CATransactionbegin];

[CATransactionsetValue:(id)kCFBooleanTrueforKey:kCATransactionDisableActions]; 

_arrowImage.hidden =YES;

[CATransactioncommit];

break;

default:

break;

}

_state = aState;

}


  5.然后在.h中定义一个一个判断是佛正在加载的属性_loading 和3个方法

//开始更新的方法

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

//当停止拖拽时调用

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

//数据加载完成后调用此方法

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


  6. 当用户刚开始滑动调用第一个方法,将_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;

@end


7.当加载结束后用户调用第三个方法,让_statu变 EGOOPullRefreshNormal,tableview也变为初始状态。这样下拉刷新就实现就完成了。


//数据加载完成后调用此方法

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

    //设置表示图的填充距离为0,即隐藏了下拉视图

[UIViewbeginAnimations:nilcontext:NULL];

[UIViewsetAnimationDuration:.3];

    //数据加载完成后,scrollView恢复位置大小

[scrollViewsetContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)];

[UIViewcommitAnimations];

// 数据加载完成,

[selfsetState:EGOOPullRefreshNormal];


}







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值