[iOS]UICollectionView循环滚动功能的实现思路

来源:互联网 发布:cda数据分析师教程 编辑:程序博客网 时间:2024/05/02 00:08


很多 APP 首页的广告都有图片循环滚动功能, 我做的项目中正好也需要这个功能

我说主要思路, 并提供我写的代码例子


广告要滚动, 首先想想具有滚动功能的原生控件有哪些, scrollView, tableView, collectionVIew, webView......

广告要水平滚动, 所以只剩 scrollView, collectionVIew 可以试试


方法一: scrollView

假设有5张图片, 分别叫 A,B,C,D,E, 每张图片放到 imageView 上, 然后 imageView 放到 scrollView 上

用户有两种操作, 向左滚, 向右滚

当向左滚, 滚到第1张时, 就是最左边那张时, 我把第5张图片给挪过来(设置 frame 值), 如下图

[A],B,C,D,E,    // 现在显示 A 图片, 我设置5张图片的 frame 值使得图片顺序变成这样

E,[A],B,C,D     // E 被挪到 A 的前面了, 实现了循环滚动, [ ]括号表示正在显示的图片


向右滚也同理, 

A,B,C,D,[E],    // 现在显示 E 图片, 在 E 显示完之后

B,C,D,[E],A     // 马上把 A 挪到 E 的右边

具体在哪里挪, 请看一下 scrollView 的所有代理方法, 想想在哪个方法里比较合适


可以优化的地方, 假设图片有很多张, 没必要创建那么多 imageView, 只要3个 imageView 就够了, 想想2个够吗?

3个 imageView, 分别叫 A,B,C, 我只显示中间那个 imageView, 用 [ ] 括住的那个

A,[B],C

C,[A],B// 向左滚, 把 C 移到了 A 的左边

B,[C],A // 再向左滚, B 移到 C 的左边


可是 N 张图片怎么放到 3 个imageView 里? 还记得<数据结构>里的循环队列吗? 

我每次去循环队列里取一张图片X作为当前显示的图, 结构如下

X前一张 ,[图片X], X后一张


C语言中数组和链表都可以实现循环队列, 想想 OC 中用什么实现循环队列?

我用 NSArray + NSInteger 索引实现, 所有图片放进 NSArray *array 里, 再来个 NSInteger index; 循环的索引

加1操作: index = (index + 1) % array.count;

减1操作: index = (index - 1 + array.count) % array.count;

加1操作取前一张, 减1取后一张

scrollView 的方法就到这里了


方法二: collectionView

由于方法一自己写的 imageView 重用太过复杂, 而且scrollView 代理方法有局限性(我想在手指离开屏幕时, 获得最终结果是左滚还是右滚,scrollView 没有这个代理方法), 导致连续滚动时会出现不连贯的问题

collectionView 自带了 cell 重用, 还可以设置为水平滚动, 所以我想到在 cell 上放 imageView, 借用collectionView的重用机制, 那怎么实现循环功能呢? 

还是有5张图片, 分别是 ABCDE, 放在数组里, A 在 0 位置, B 在 1 位置,,,,如此类推

我把这组图片复制100份, 存进数组里, 那么数组里面的东西就像这样

ABCDEABCDEABCDE....// 看出规律没, ABCDE 循环放, 这个数组就有 100*5 个元素

然后我把 collectionView 定位到中间的第 50 组的, 第0张图片来显示, 如下图, 前面还有49组, 后面还有50组图片

......ABCDE,[A]BCDE,ABCDE......  

这样就实现了循环滚动了吧, 但是有问题

问题1. 图片很多, 很耗内存

问题2. 用户一直往前滚动, 迟早会滚到边界


问题1解决方法

还记得<数据结构>里的地址排序吗, 不记得我来说说

假如数组里的元素很大(1MB 以上), 移动很不方便的时候, 要对他排序, 那么我可以对他的地址进行排序, 而不移动元素内容, 我来一张表, (地址, 元素的地址), 保存排序结果即可, 排序不是重点不展开了


所以那 5 图片我没必要复制 100 份了, 我把5张图片的地址, 复制100份, 存在数组里, 数组地址是 long int 型的吧

假设 long int 占 8个字节, 那么这个数组大小是 100*5*8 = 4000 个字节, 差不多 4KB 而已, 项目中一张图片是 200多k

那么我就用, 下面的数组表示图片了, 拿到数组内容, 再去图片数组里拿具体图片即可, 解决内存占用问题

......012340123401234......


问题2解决方法

用户一直往前滚动, 迟早会滚到边界, 这个很好解决, 当 collectionView 停止滚动时, (想想停止滚动是哪个代理方法), 我去把 collectionView 重新定位到第50组的图片那里去, 并且不用动画的滚动, 即可

除非有人手指不离开屏幕, 一直朝一个方向滚 collectionView, 导致 collectionView 动画停止不了, 无法重定位到中间

那么可以把100份的数组, 开到1000份, 那么就有 5000个图片地址了, 他手指不松开的滚动, 还是会到边界, 遇到这么无聊的人, 我也是给他跪了.... 


代码下载地址:

collectionView循环滚动   http://pan.baidu.com/s/1skeLQLf

scrollView循环滚动   http://pan.baidu.com/s/1KrIuM




0 0
原创粉丝点击