UITableView:下拉刷新和上拉加载更多

【转载请注明出处】

本文将说明具有多个section的UITableView在使用下拉刷新机制时会遇到的问题及其解决方案。

工程地址在帖子最下方,只需要代码的直拉到底即可。

【目录】

1、现象分析;

2、解决方案;

3、工程地址。

1、现象分析 
当前的大多数支持下拉刷新的库,都是通过修改UIScrollView的contentInset实现的。

(可参见我的这篇帖子:UITableView:下拉刷新和上拉加载更多)

使用这种方法带来的问题是,当UITableView具有多个section时,依照上述方式使用下拉刷新,在加载过程中上滑,会出现样式跑版:

为了分析出问题所在,首先在控制台打印出正常状态下UITableView的所有子View :

比较各行的frame.origin.y可以看出,UITableView的section headerView是和cell一起,按顺序放入基类UIScrollView的内容View中的。

再看加载中时的情况:

从Pull2RefreshView的frame可以看出,此时UITableView的contentInset已经被修改为(65, 0, 0, 0)。而section headerView和各个cell的frame.origin.y不受影响,和预期一致。

最后看看在加载中状态下上滑时的情况,将UITableView上滑至上方图中所示情境,即第一行的cell刚刚好越过section headerView:

可以看到,section headerView的frame.origin.y发生了变化,它和第二个cell一起被放在了第一个cell的下方,即:

section headerView.frame.origin.y == firstCell.frame.origin.y + cellHeight;

继续上滑,可以看到section headerView.frame.origin.y不断变化,但在界面显示上,始终位于距离UITableView.frame.origin.y为65(即修改后contengInset.top的值)的位置,直到下一个section headerView出现时,才随着cell向上移动,如图:

【注意:不论在任何情况下,第一个cell的frame.origin.y始终为section headerView的高度,在本例中为23,即使它已经处于section headerView的上方】

2、解决方案 

由此,可以粗略得出以下结论:

A、 section headerView和cell之间并不是简单的顺序摆放的关系,它们之间可以发生重叠;

B、 section headerView在界面上的显示位置由UITableView.contentInset.top决定,直到被下一个section headerView替代。

如此,想要在滑动时修改section headerView的显示位置,令其和cell一起移动,只需要动态地修改UITableView.contentInset.top即可,如下:

 1  - (void)scrollViewDidScroll:(UIScrollView *)scrollView
 2   {
 3       //added 2013.11.28 动态修改headerView的位置
 4       if (headerRefreshing)
 5       {
 6           if (scrollView.contentOffset.y >= -scrollView.contentInset.top
 7               && scrollView.contentOffset.y < )
 8           {
 9               //注意:修改scrollView.contentInset时,若使当前界面显示位置发生变化,会触发scrollViewDidScroll:,从而导致死循环。
              //因此此处scrollView.contentInset.top必须为-scrollView.contentOffset.y
              scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, , , );
          }
          else if (scrollView.contentOffset.y == )//到0说明headerView已经在tableView最上方,不需要再修改了
          {
              scrollView.contentInset = UIEdgeInsetsZero;
          }
      }
      
      //other code here...
  }

Added 2014.7.24:

对于不需要提交到AppStore的应用,还有一个更简单的办法,即覆盖UITableView的私有方法。

- (BOOL)allowsHeaderViewsToFloat
{
return NO;
} - (BOOL)allowsFooterViewsToFloat
{
return NO;
}

3、工程地址

使用iOS 6.1 SDK编译,使用ARC。
地址:https://github.com/cDigger/CDPullToRefreshDemo

【参考】

1、Section Headers in UITableView when inset of tableview is changed

http://stackoverflow.com/questions/5466097/section-headers-in-uitableview-when-inset-of-tableview-is-changed

2、Change Default Scrolling Behavior of UITableView Section Header

http://stackoverflow.com/questions/664781/change-default-scrolling-behavior-of-uitableview-section-header

下拉刷新和UITableView的section headerView冲突的原因分析与解决方案的更多相关文章

  1. UITableView:下拉刷新和上拉加载更多

    [转载请注明出处] 本文将说明让UIScrollView支持"下拉刷新"和"上拉加载更多"的实现机制,并实现一个可用的tableView子类,以下主要以&quo ...

  2. IOS学习笔记34—EGOTableViewPullRefresh实现下拉刷新

    移动应用开发中有这么一种场景,就是在列表中显示的数据刷新,有点击刷新按钮刷新的,也有现在最流行的由Twitter首先推出的下拉刷新功能,在IOS中,使用下拉刷新更新UITableView中的数据也用的 ...

  3. listview下拉刷新和上拉加载更多的多种实现方案

    listview经常结合下来刷新和上拉加载更多使用,本文总结了三种常用到的方案分别作出说明. 方案一:添加头布局和脚布局        android系统为listview提供了addfootview ...

  4. ListView装上拉电阻下拉刷新

    主要用到了这个几个文件.MainActivity是界面的Activity,MyAdapter是ListView的自己定义适配,MyListView是自己定义带头部LIistView,假设仅仅须要上拉载 ...

  5. 【转载】Android中ListView下拉刷新的实现

    在网上看到一个下拉刷新的例子,很的很棒,转载和更多的人分享学习 原文:http://blog.csdn.net/loongggdroid/article/details/9385535 ListVie ...

  6. Android中ListView下拉刷新的实现

    ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考.那我就不解释,直接上代码了. 这里需要自己重写一下ListView,重写代码如下: packa ...

  7. ListView下拉刷新上拉加载更多实现

    这篇文章将带大家了解listview下拉刷新和上拉加载更多的实现过程,先看效果(注:图片中listview中的阴影可以加上属性android:fadingEdge="none"去掉 ...

  8. UITableView与UISearchController搜索及上拉加载,下拉刷新

    #import "ViewController.h" #import "TuanGouModel.h" #import "TuanGouTableVi ...

  9. IOS UITableView下拉刷新和上拉加载功能的实现

    在IOS开发中UITableView是非常常用的一个功能,而在使用UITableView的时候我们经常要用到下拉刷新和上拉加载的功能,今天花时间实现了简单的UITableView的下拉刷新和上拉加载功 ...

随机推荐

  1. SQL之case when then用法详解

    case具有两种格式.简单case函数和case搜索函数. <span style="font-size:14px;">--简单case函数 case sex when ...

  2. C语言文法推导

  3. PAT L1 - 056 猜数字

    https://pintia.cn/problem-sets/994805046380707840/problems/994805074646122496 一群人坐在一起,每人猜一个 100 以内的数 ...

  4. Tomcat指定JDK路径

    一.应用实例 一般情况下一台服务器只跑一个业务,那么就直接配置一套环境,设置好Java环境变量即可.某些时候一台服务器上会安装多个业务,而且各个业务需要的JDK版本各不相同,或者为了使业务独立开来,需 ...

  5. 手机uc不支持伪元素使用animation动画;移动端background-attachment:fixed不兼容性

    20170503 1.手机uc不支持伪元素使用animation动画 (暂未解决) 2.移动端background-attachment:fixed不兼容性,没有任何效果, element:befor ...

  6. Java实现Websocket

    Websocket介绍 在一个 WebSocket应用中, 服务器发布一个 WebSocket端点, 客户端使用这个端点的URI来连接服务器.建立连接之后,websocket协议是对称的;客户端和服务 ...

  7. 洛谷 P2647 最大收益

    我是题面 恩,贪心,鉴定完毕. 一个物品是否放进来,取决于它是否能对答案做出贡献. 那物品i的贡献就是\(w[i]-r[i]\) 可是收益的减少是会叠加的 那就是\(w[i]-j*r[i]\),j表示 ...

  8. [BZOJ4103][Thu Summer Camp 2015]异或运算 可持久化Trie树

    4103: [Thu Summer Camp 2015]异或运算 Time Limit: 20 Sec  Memory Limit: 512 MB Description 给定长度为n的数列X={x1 ...

  9. 【BZOJ4197】【NOI2015】寿司晚宴(动态规划)

    [BZOJ4197][NOI2015]寿司晚宴(动态规划) 题面 BZOJ 从\([2,n]\)中选择两个集合(可以为空集),使得两个集合中各选一个数出来,都互质. 求方案数. 题解 对于\(500\ ...

  10. 【CF625E】Frog Fights(模拟)

    [CF625E]Frog Fights(模拟) 题面 CF 洛谷 翻译: 有\(n\)只青蛙在一个被分为了\(m\)等分的圆上,对于每份顺时针依次标号. 初始时每只青蛙所在的位置是\(p_i\),速度 ...