回头看UITableView(三)-下拉刷新的实现

最近陷入了项目中一个日历月视图与周视图切换效果的实现,长时间没有实现想要的效果,沮丧至极。烦请有好想法的同学指点一二,在线等@留什么白


结束例行的啰嗦,进入正题。

大家可能都用过MJRefresh,十分之方便,李明杰老师借助runtime的特性,极尽之能,让千千万万小白开发者和遵循不重复制造轮子原则的开发者用最少的代码就实现了界面下拉刷新的功能。我们今天不谈runtime的黑魔法,而是UITableView最常见的刷新数据方式下拉刷新的实现过程。

首先,我们定义三个枚举值

typedef NS_ENUM(NSUInteger, RefreshState) {
    RefreshStateNormal,//正常
    RefreshStatePulling,//释放即可刷新
    RefreshStateLoading,//加载中
};

分别表示正常状态、释放即可刷新状态、加载中状态

为了简单说明,我们只用一个UILabel来表现就可以,把它放在内容上方,也就是正常情况下看不到的地方,只有下拉的时候才能看到。

UILabel的位置

然后我们估算一个大体的距离,从而确定触发加载状态的临界点。

简单描述一下将要实现的情形:

我们往下滑动视图,如果视图下滑到触发点,状态变为RefreshStatePulling,即标签文字变为“松手即可刷新”。
接下来有两种状况会发生:一,松开手;二,不松手,又向初始位置滑。第一种情况,当你松开手时,因为UIScrollView有回弹效果,视图会往上滑动,当到达触发点时,状态改为RefreshStateLoading,即视图停在当前位置,不受回弹作用影响,标签文字变为“加载中...”,等加载动作完成之后,手动触发复原动作,视图滑到原始状态 RefreshStateNormal,同时标签文字变为‘下拉刷新’;第二种情况,你没有松手,然后又往回滑动,当到达触发点以上时,状态变为初始状态RefreshStateNormal

如果你对上述过程不是很了解的话,那你随便找个带下拉刷新的应用试试就行了,不用温柔,越暴力越好。弄清上述过程是实现整个流程的基础。

接下来要做的就是决定什么时候改变状态了,参照上述过程,我们在UIScrollView的代理函数scrollViewDidScroll:监控contentOffset的变化,再结合isDragging属性就可以改变状态了。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if(scrollView.contentOffset.y < -SwitchPoint-self.originalInsetTop){
        if(self.refreshState == RefreshStateNormal){//小于临界值(在触发点以下),如果状态是正常就转为下拉刷新,如果正在刷新或者已经是下拉刷新则不变
            self.refreshState = RefreshStatePulling;
        }
    }else{//大于临界值(在触发点以上,包括触发点)
        if(scrollView.isDragging){//手指没有离开屏幕
            if(self.refreshState == RefreshStatePulling){//原来是下拉的话变成正常,原来是刷新或者正常的话不变
                self.refreshState = RefreshStateNormal;
            }
        }else{//手指离开屏幕
            if(self.refreshState == RefreshStatePulling){//原来是下拉的话变成加载中,原来是加载中或者正常的话不变
                self.tableView.contentInset = UIEdgeInsetsMake(self.originalInsetTop+SwitchPoint, 0, 0, 0);//改变contentInset的值就可以取消回弹效果停留在当前位置了 关于contentIinset的介绍,可以查看我的上一篇文章
                self.refreshState = RefreshStateLoading;
            }
        }
    }    
}

这段代码决定了UIScrollView每个时刻的状态,那么接下来的就简单多了,只要重写一下setRefreshState:方法就可以了。

- (void)setRefreshState:(RefreshState)refreshState{
    _refreshState = refreshState;
    switch (refreshState) {
        case RefreshStateNormal:
            self.pulldownLabel.text = @"下拉刷新";
            [self.pulldownLabel sizeToFit];
            break;
        case RefreshStateLoading:
            self.pulldownLabel.text = @"正在刷新...";
            [self.pulldownLabel sizeToFit];
            if(self.refreshBlock){
                self.refreshBlock();//这里就是你要执行的耗时的操作
            }            
            break;
        case RefreshStatePulling:
            self.pulldownLabel.text = @"松开即可刷新";
            [self.pulldownLabel sizeToFit];
            break;
        default:
            break;
    }
}

看一下我们的效果:


平凡而简单的效果

当然你会说这不够diao,不够炫酷,人家的效果都是这样:

又被你发现了,😂,我满(hao)是(wu)虔(jie)诚(cao)地盗了大神的图,@M了个J,大神,膝盖已发货,请验收。

那么我们怎么实现这样的效果呢,很简单,在上边设置状态的代码里添加动画就行了。来一段伪的代码:

case RefreshStateNormal:
     self.pulldownLabel.text = @"下拉刷新";
     [UIView animateWithDuration:0.3 animations:^{
         self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI/2);//箭头旋转180º
     }];
     break;

还有一点需要强调,在scrollViewDidScroll:里保持加载状态时修改了contentInset,所以取消加载状态恢复原状时只需...如此如此:
- (void)endRefresh{
if(self.refreshState == RefreshStateLoading){
self.refreshState = RefreshStateNormal;
[UIView animateWithDuration:0.3 animations:^{
self.tableView.contentInset = UIEdgeInsetsMake(self.originalInsetTop, 0, 0, 0);
} completion:nil];
}
}

OK,希望看到这里你能理解下拉刷新的整个过程及原理了,欢迎指正和打击。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,378评论 25 707
  • 放松是一种慈悲,对人不苛求,对已不苛责。 今天的领航,明显更放松了些,开始可以跟随分享着的故事和情绪,可...
    山间竹音阅读 147评论 0 0
  • 网咖行业是由网吧演变过来的,参考前瞻 产业研究院《2016-2021年中国网吧行业市场前瞻与投资战略规划分析报告》...
    崇拜_e716阅读 467评论 0 1
  • 工作,不同于生活。 生活,其实也是工作。 22岁之前,我的生活是上学。 22岁之后,我的生活有工作。 学习是轻松的...
    零兰阅读 154评论 0 2