文章标题

开源中国iOS客户端学习——(二)下拉刷新特效EGOTableViewPullRefresh
分类: 菜鸟学iOS的笔记 2012-12-17 12:25 13656人阅读 评论(29) 收藏 举报
打开开源中国iOS客户端应用程序第一步就是加载数据,经常我们在第二次以后打开的时候,我们界面显示的是上一次更新的数据,此时我们想看最新内容就需要去刷新数据加载这些内容,加载需要一个等待过程,如何能让用户在等待过程中不焦急,能够等待这个过程完成,这就需要给用户一个心里安慰,让用户知道该软件正在很努力很努力的执行自己命令,这就需要我们为自己应用程序添加一些特效;

  开源中国iOS客户端用到了不少特效,这些特效在当前很多应用软件中都比较流行,基本上这些特效都属于第三方类库,本次想说的是下拉刷新特效,EGOTableViewPullRefresh最开始是在Twitter中使用,最后做了开源,然后很多应用添加这个特效,常作为加载数据时将等待时间作为一个动画来过渡;

下拉刷新类库EGOTableViewPullRefresh资源文件下载地址:
https://github.com/enormego/EGOTableViewPullRefresh/tree/

先这个特效的效果图

在EGOTableViewPullRefresh资源文件中有两个文件,.m和.h文件,还有资源图片,就是下拉刷新箭头

资源图片一共4种色,可以根据喜好选用不同色的箭头,只需在EGORefreshTableHeaderView.m文件中修改一下。按照大小尺寸又可分两种,较大尺寸是用于iPad上使用的。

针对这些第三方类库,我们没必要去深入研究它们内部实现机制原理,只要知道怎么用就可以。不过,看一看别人实现原理,学学别人的方法还是很不错的,了解下人家牛人程序是怎么写的;

EGORefreshTableHeaderView.h
[cpp] view plaincopy

import

import

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 arrowImageName:(NSString )arrow textColor:(UIColor )textColor {
if((self = [super initWithFrame:frame])) {
// self.view自动适应bounds的宽度
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
// self.view背景色和透明度设置
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 = textColor;  

// label文本阴影颜色
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 = [[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 = textColor;  
    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:arrow].CGImage;

// 判断设备版本,因为一些iOS特性是在最后新增的,要求设备配置高一些,所以做一下判断

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;  

}
[cpp] view plaincopy
//初始化当前视图的frame
- (id)initWithFrame:(CGRect)frame {
return [self initWithFrame:frame arrowImageName:@”blueArrow.png” textColor:TEXT_COLOR];
}

pragma mark -

pragma mark Setters

//获取最后一次更新的时间
- (void)refreshLastUpdatedDate {

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

    NSDate *date = [_delegate egoRefreshTableHeaderDataSourceLastUpdated:self];  

// NSDateFormatter实例创建字符串,来表示NSDate和NSCalendarDate对象,已预订格式化字符串输出
[NSDateFormatter setDefaultFormatterBehavior:NSDateFormatterBehaviorDefault];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
// 设置日期输出格式
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
// 设置时间显示格式
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];

// _lastUpdatedLabel.text = [NSString stringWithFormat:@”Last Updated: %@”, [dateFormatter stringFromDate:date]];
_lastUpdatedLabel.text = [NSString stringWithFormat:@”最后更新: %@”, [dateFormatter stringFromDate:date]];
// 存储_lastUpdatedLabel.text内容,放到字典中
[[NSUserDefaults standardUserDefaults] setObject:_lastUpdatedLabel.text forKey:@”EGORefreshTableView_LastRefresh”];
// 将NSUserDefaults存储数据放到磁盘
[[NSUserDefaults standardUserDefaults] synchronize];

} else {  

    _lastUpdatedLabel.text = nil;  

}  

}
[cpp] view plaincopy
- (void)setState:(EGOPullRefreshState)aState{

switch (aState) {  
        /*触摸屏幕下拉状态*/  
    case EGOOPullRefreshPulling:  

// _statusLabel.text = NSLocalizedString(@”Release to refresh…”, @”Release to refresh status”);
_statusLabel.text = @”松开即可刷新”;
// 设置下拉刷新过程,箭头的图片的一个动画过程
[CATransaction begin];
// 动画时间
[CATransaction setAnimationDuration:FLIP_ANIMATION_DURATION];
// 下拉刷新箭头一个翻转过程,(M_PI / 180.0)是角度转换为弧度

        _arrowImage.transform = CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.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…”, @”Pull down to refresh status”);
_statusLabel.text = @”下拉可以刷新”;
[_activityView stopAnimating];
[CATransaction begin];
// 因为下拉刷新完成好就不需要下拉动画,此时_activityView动画显示
// 显示事物关闭动画效果 kCFBooleanTrue关闭 kCFBooleanFalse开启
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
_arrowImage.hidden = NO;
_arrowImage.transform = CATransform3DIdentity;
[CATransaction commit];
// 更新下时间
[self refreshLastUpdatedDate];

        break;  
        /*触摸手指松开,完成下拉操作的状态*/  
    case EGOOPullRefreshLoading:  

// _statusLabel.text = NSLocalizedString(@”Loading…”, @”Loading Status”);
_statusLabel.text = @”加载中”;
[_activityView startAnimating];
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
_arrowImage.hidden = YES;
[CATransaction commit];

        break;  
    default:  
        break;  
}  

_state = aState;  

}
[cpp] view plaincopy

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) {

    BOOL _loading = NO;  
    if ([_delegate respondsToSelector:@selector(egoRefreshTableHeaderDataSourceIsLoading:)]) {  
        _loading = [_delegate egoRefreshTableHeaderDataSourceIsLoading:self];  
    }  
    
    if (_state == EGOOPullRefreshPulling && scrollView.contentOffset.y > -65.0f && scrollView.contentOffset.y < 0.0f && !_loading) {  
        [self setState:EGOOPullRefreshNormal];  
    } else if (_state == EGOOPullRefreshNormal && scrollView.contentOffset.y < -65.0f && !_loading) {  
        [self setState:EGOOPullRefreshPulling];  
    }  
    

    // 设置下拉属性scrollView框架恢复初始位置
    if (scrollView.contentInset.top != 0) {
    // A UIEdgeInsets struct whose top, left, bottom, and right fields are all set to the value 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];  
    

    }

}
//数据加载完成后调用此方法
- (void)egoRefreshScrollViewDataSourceDidFinishedLoading:(UIScrollView *)scrollView {

[UIView beginAnimations:nil context:NULL];  
[UIView setAnimationDuration:.3];  

// 数据加载完成后,scrollView恢复位置大小
[scrollView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)];
[UIView commitAnimations];
// 数据加载完成,
[self setState:EGOOPullRefreshNormal];

}
[cpp] view plaincopy

pragma mark -

pragma mark Dealloc

  • (void)dealloc {

    _delegate=nil;
    _activityView = nil;
    _statusLabel = nil;
    _arrowImage = nil;
    _lastUpdatedLabel = nil;
    [super dealloc];
    }

@end

当我们想使用这个下拉刷新类库的时候,在使用类里声明这个协议,把当前类self交付给下拉刷新库的协议对象,也就是xx.delegate=self;
怎样让其他类来使用这里面效果,这时我们就可以委托另一个类来实现协议的方法。
选中一个协议方法,右键选择Jump to Definition就可以看到哪些类被委托了,怎样使用了这个类的协议方法:

正在学习过程中,错误之处请指正,欢迎交流,共同学习;

欢迎转载分享,请注明出处http://blog.csdn.net/duxinfeng2010

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值