1.任务需求:
顶部有一个UIScrollview,用于显示分类标签,每个分类标签对应一个UITableView,所有的UITableview放在底部的UIScrollview中以便于滑动。可以通过点击顶部分类标签来滑动到对应视图,也可以通过手势左右滑动切换页面。
2.初遇问题:
点击顶部分类标签滑动时,由于需要通过调用UIScrollview的setContentOffset方法,因此两个不相邻的UITableview之间所有的UITableview都会闪过。因此,由于动画持续时间不变,两个UITableview之间间隔的UITableview越多,每个UITableview闪过的时间就越短,用户体验也越差。
3.解决思路:
//关键在于这个方法的巧妙运用
[scrollView setContentOffset:(CGPoint)offset animated:(BOOL)];
这个函数表示通过移动scrollView,将CGPoint设置为当前界面的左上角。animated的值表示是否需要使用动画进行移动。
基于这个函数的使用原理,我们可以在滑动之前,将目的table的前一个table设置成和原有table一样,然后在关闭动画的情况下移动到这个table,再在开启动画的情况下移动到目的table。
4.解决方法:(假设从左至右移动)
考虑到UITableView继承自UIView,是一个对象类型,因此不能执行浅拷贝,而UIView没有copyWithZone方法,不能执行深拷贝,所以直接复制table不太现实。但是可以通过以下方法
//RootScrollView是一个单例对象
//该方法表示将index为duplicateTableFromIndex的table复制到新的位置上
[[RootScrollView shareInstance]duplicateTableFromIndex: previousButtonTag ToIndex:nextButtonTag - 1];
修改previousTable的frame,移动到nextTable-1的位置。并且将底部的table的hidden属性设置为YES。
[[RootScrollView shareInstance] setContentOffset:CGPointMake(KScreenWidth * (BUTTONID - 1), 0) animated:NO];
这个方法表示移动UIScrollView使得destinationTable-1显示在当前界面中。
再通过
[[RootScrollView shareInstance] setContentOffset:CGPointMake(BUTTONID * KScreenWidth, 0) animated:YES];
在开启动画的情况下移动到目的table。
最终我们需要执行reset方法,将destinationTable-1的hidden改回NO,并将sourceTable的frame改为初始值。
- (void)reset{
if (sourceTable != nil) {
sourceTable.frame = previousFrame;
}
if (destinationTable != nil) {
destinationTable.hidden = NO;
}
}
具体地说就是,如果我们想从1号table跳转到6号table,可以把1号table的frame改成和5号table一样,然后在不开启动画的的情况下,让scrollview显示5号table所在的位置。由于以上两步一前一后执行(相隔时间忽略不计),此时用户感觉不到视图的移动,然后再在开启动画的情况下,自然地滑动到6号table即可。
5.再遇问题
无法流畅切换页面,从sourceTable切换到destinationTable时,destinationTable的前一个table依然会闪过。比如从1号table切换到6号table,依然会看到5号table。
6.问题分析
setContentOffset方法在animated = YES时,执行需要时间。而在这个方法执行后的瞬间,就执行了reset方法。也就是当前scrollView刚开始滑动时,sourceTable就被还原到初始位置,destinationTable-1的hidden被设置为NO。也就是说遮住destinationTable-1的sourceTable被移走,destinationTable-1被显露出来,因此这就是错误的原因。
7.问题解决
scrollView有一个代理方法
(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
这个方法将在animated结束的时候执行方法内的代码。所以解决方法为讲reset方法改在这里执行即可。
不太清楚怎么在博客里上传文件,如果还有不明白的地方或是纠正bug,可以直接留言,相互讨论。
原文:http://blog.csdn.net/abc649395594/article/details/44632441