tableView中的refresh的原理探究及相关基础概念

        最近有时间自己实现了tableView中的上拉刷新和下拉加载更多的功能,同时发现了自己在基础知识上的盲点和不足,顺便补习一下,我把代码拿出来跟大家分享一下。

一、bounds、frame等重要概念

frame: 该view在父view坐标系统中的位置和大小。(参照点是,父亲的坐标系统)

bounds:该view在本地坐标系统中的位置和大小。(参照点是,本地坐标系统,就相当于View自己的坐标系统,以0,0点为起点)

contentSize:滚动视图的范围,也就是所有内容的大小

contentOffset:The point at which the origin of the content view is offset from the origin of the scroll view. (文档描述)意思就是内容区域和scrollview的frame区域的高度差,注意一定是frame,这点下面会解释。

contentInset:The distance that the content view is inset from the enclosing scroll view.(文档描述)意思是在contentView周围增加边距,当有contentInset时会让用户感觉内容距离边框有一定的距离,同时它并没有占用增加的边距内容,隐藏的视图会显现出来,一会在代码中会用到。(详见图二)

关于bounds需要好好理解一下,它相当于在frame上层浮动的一层区域,而且是负责显示内容,只不过它是边界,contentView是中间的内容。一般一个View的bounds的原点都是(0,0),因为是以自己为坐标系,但是如果你改变了它的原点,那么该View的子View都会以改变后的原点来进行布局,总结为bounds的原点会影响其子视图的显示位置。

这些概念非常重要,建议大家写写demo具体观察一下。

推荐一个关于这方面介绍的好文章:iOS View的Frame和bounds之区别,setbounds使用(深入探究) - 郭晓东的专栏 - CSDN博客

二、tableView的重要概念

tableview的内容包括:1.cell,2.tableHeaderView / tableFooterView,3.sectionHeader / sectionFooter

contentOffset.y == frame顶部 和 contentSize顶部 的差值

inset是紧紧粘着内容,如果有tableHeaderView / tableFooterView,会在其上 / 下紧贴显示(详见图一)

图一
图二

如果我说的太啰嗦可以直接看图,把我说的当成加强理解就行了。

三、代码分析

接下来进行代码分析,在文章末尾有百度云的传送门。

先看一下效果图(iPhone X系列手机和iPhone8之前的都适配)


这个demo是普通的UITabBarController加UINavigationController,主页控制器是UITableViewController。

以下是用到的属性

图四

首先初始化头部和底部的刷新控件,由于考虑到一般应用的头部都有广告或者搜索框之类的东西,所以header直接采用add subview的方式,直接紧贴着内容添加,也就是在广告条的上方。

图五

footer由于一般底部没什么需要特别添加的,所以直接复制给tableFooterView。

图六

接下来就要监听header的位置变化来实现其中文字的变化,当然图片变化也可以,添加图片后在合适的时候直接旋转。我在scrollViewDidScroll方法中调用dealHeader和dealFooter,重点分析header的处理。


图七
图八

图八中offsetY是一个static变量,因为它是一个固定的临界值,getRectNavAndStatusHight是一个获取顶部导航最大高度的宏,在iPhone X之前和之后的机型中都可以用。offsetY的意思是导航栏的最大高度加上header的高度,之所以加符号是由于下拉时contentOffsetY时负值,当下拉的Y值的绝对值超过offsetY,也就是self.tableView.contentOffset.y < offsetY时,header可以变换样式。这里在解释一下contentOffset,它是图二中你见到的那种样子,手指下滑时也就是下拉时越来越小直到变成负值,手指上滑时值越来越大。而这里有个很有意思的注意点,初始位置contentOffset.y是-88,也就是导航栏的高度,这是因为contentView是我们可视的区域,而bounds的原点是(0,-88),也就印证了我一开始说的bounds负责显示内容,只不过它是边界,contentView是中间的内容。我将打印结果截图了,大家可以分析一下。

bounds也影响了子视图显示位置,包括tableHeaderView的frame的原点是紧贴导航栏的左下角,header的frame的原点是(0,-50),也是以导航栏的左下角为参照。而tableView是占满整个屏幕的,这点通过查看视图可以印证(见图十二,那个紫色的区域就是我选中tableView后显示的)。


图九
图十


图十一


图十二

回到处理header上,之前能够通过偏移量处理header的变化,接下来就是当用户下拉松手后的处理,当偏移量没有超过临界值时不做操作,直接由scrollViewDidScroll中的dealHeader使其恢复原样,如果超过临界值则调用headerBeginRefreshing方法,监听用户的手势拖拽是scrollViewDidEndDragging:(UIScrollView*)scrollView willDecelerate:(BOOL)decelerate方法。在开始刷新的方法中先判断是不是正在处于刷新,如果是就直接返回,主要是防止在真正的应用中多次向服务器发出请求。在demo中没有接口请求所有我都是通过延迟来模拟的,contentInset的作用就是使得“正在请求数据”的header样式可以停留在用户的视野中。我加了一个动画让其看起来自然些。然后就是调用loadNewData方法请求数据,大家用的时候直接在这里面放入真正的接口请求然后reloadData就可以。最后结束刷新,没什么好说的直接看代码就能看懂,注释写的也很详细。

图十三
图十四
图十五
图十六

以上就是整个下拉刷新的实现,主要是为了加深对tableView的一些属性的理解。上拉刷新的过程跟这个差不多,我就不细说了,强调一下临界值的计算: CGFloat footerOffset = self.tableView.contentSize.height - self.tableView.frame.size.height + kTabBarHeight_X; kTabBarHeight_X是底部导航栏的高度,也是一个宏,在iPhone X之前和之后的机型中都可以用。由于是为了让footer的显示完全超过TabBar的上沿后才刷新,所以最后要加上TabBar的高度,前面两个值相减是tableView的contentOffset的Y值计算方法,但显然不是超过tableView的底部而是超过TabBar的上沿,还记不记得tableView的视图查看,这块需要好好理解一下才能想明白。footer没有想header那样处理的那么复杂有三段变化,所以没有在监听结束拖拽的方法中去处理刷新,想加的童鞋可以照着header来处理。

demo地址:链接:https://pan.baidu.com/s/1Ph-i3KFJpCmKQNapWNUDrA 密码:uk8p

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

推荐阅读更多精彩内容