下拉刷新和UITableView的section headerView冲突的原因分析与解决方案
2013-11-28 21:48
495 查看
UITableView:下拉刷新和上拉加载更多
[b]【转载请注明出处】[/b]本文将说明具有多个section的UITableView在使用下拉刷新机制时会遇到的问题及其解决方案。
工程地址在帖子最下方,只需要代码的直拉到底即可。
【目录】
1、现象分析;
2、解决方案;
3、工程地址。
[b]1、现象分析
[/b]当前的大多数支持下拉刷新的库,都是通过修改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的上方】
[b]2、解决方案 [/b]
由此,可以粗略得出以下结论:
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 < 0)
8 {
9 //注意:修改scrollView.contentInset时,若使当前界面显示位置发生变化,会触发scrollViewDidScroll:,从而导致死循环。
//因此此处scrollView.contentInset.top必须为-scrollView.contentOffset.y
scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
}
else if (scrollView.contentOffset.y == 0)//到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冲突的原因分析与解决方案
- 77.下拉刷新MJRefresh和UITableView的section headerView冲突的原因分析与解决方案
- 下拉刷新和UITableView的sectionHeaderView冲突的问题
- 下拉刷新时UITableView的section headerView冲突的解决
- 针对错误 “服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF” 的原因分析
- UITableView的代理方法viewForHeaderInSection不执行的原因
- iOS UITableView的嵌套和sectionHeaderView悬停的解决方案
- UITableView的section header view悬停和取消的方法
- UITableView左右滑动cell无法显示“删除”按钮的原因分析
- 让UITableView的section header view不悬停的方法
- UITableView的代理方法viewForHeaderInSection不执行的原因
- 让UITableView的section header view不悬停,让UITableView的section headerview取消粘性
- UITableView的section header view悬停的方法
- UITableView的section设置了headerView导致下滑的时候headerView跟着滚动的解决方法
- UITableView中关于viewForHeaderInSection的一点小坑
- UItableview section headerview黏性
- UITableView headerViewForSection 返回 (空值)
- iOS UITableView:section的Header以及Footer不悬浮停留在屏幕的方法(非在scrollView代理实现的方法)
- 解决RecyclerView上拉加载、下拉刷新、Header和Footer的第三方解决方案
- UITableView heightForHeaderInSection遇到的坑