美文网首页iOS不留白iOS Blog买不来的iOS实用技巧
回头看UITableView(三)-下拉刷新的实现

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

作者: 留什么白 | 来源:发表于2015-09-14 23:44 被阅读2646次

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


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

    大家可能都用过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,希望看到这里你能理解下拉刷新的整个过程及原理了,欢迎指正和打击。

    相关文章

      网友评论

      • 传递正正正能量:楼主你好,那个带动画的有demo吗,lizhimibiao@163.com
      • MrBeave丶彬彬:求源码 1193599409@qq.com 谢谢兄弟
      • syihh:大神也给我发一份源码呗~谢谢~ 100116067@qq.com
      • Cheney_Chen:求源码 108288782@qq.com 谢谢
      • 13ba66721fb5:可以把源码发来围观一下吗邮箱1574463301@qq.com
        留什么白:@童心未泯wtt 已发
      • NS西北风:大神,求源码,,
        NS西北风:@留什么白 如果方便,麻烦发一份到这个邮箱2057817622@qq.com。谢谢。。。。
        留什么白:@NS西北风 由于主要讲实现原理,而且全部代码基本都在文中了,所以就没准备把粗糙的代码放上。当然,如果你想要,我回头给你一份
      • NS西北风:兄弟,能否把你的文章对于的代码释放出来,让兄弟们围观围观。

      本文标题:回头看UITableView(三)-下拉刷新的实现

      本文链接:https://www.haomeiwen.com/subject/rfypcttx.html