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

发布于:2021-10-16 16:34:02



很多 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









相关推荐

最新更新

猜你喜欢