iOS开发--轮播图(无限循环)新玩法--视差轮播--无限循环的新思路(两个UIImageView足矣)
2016-03-08 15:34
585 查看
老赖本来说要更新iOS学习课程,可走神弄了一下午的轮播图,这里把整个过程记录下来吧,对有需要的好朋友,或许有点儿小小的帮助.
首先说,轮播图,这个东西,做开发的应该都会,不过实现的的逻辑思路有所不同.
方法一
比方说固定有5张图,最基本的实现方法就是,在scrollView上添加7张图片,排列方式是:
五一二三四五一
当图片滑到最左边,也就是”五”这个图片的时候,让scrollView调用setContentOffset 这个方法,直接跳转到倒数第二个张上面,也是”五”,所以肉眼是看不出scrollView移动的.
注意这里的跳,不能开启动画.同理,当scrollView滑到最后一个,让它瞬间跳到左边的”一”这张上去…这样就实现了无限循环滚动.
这个方法,非常巧妙,平面理解有点儿费劲,不过老赖理解之—>你拿张纸条,让它收尾相连,形成一个空间的圆圈闭环,这样,估计你瞬间里明白了这个瞬间跳转是怎么回事了!
先来看看这种方法的效果图:如下
看了上面的效果图后,问题也就出来了,这里有少量的图片,可以直接把图片的imageView加载到scrollView上.但是,如果图片多呢,50张?100张?创建100个imageView加到scrollView上,内存也吃不消吧.
对了,有好朋友,应该想到了,可以用–复用机制!
方法二:
复用机制的好处,在tableView用的淋漓尽致,做轮播图,咱们用它的亲戚,collectionView.因为系统空间本身就有复用机制,无论你加载多少照片,它只创建了两个cell,这样就大大的优化APP性能.
具体的详情,老赖这里不详细阐述了,照旧贴出相关链接:
http://www.cnblogs.com/wendingding/p/3890850.html
http://www.cnblogs.com/wendingding/p/3890953.html
这两篇是有关collectionView做轮播图的,当然,这是大神的系列,好朋友们,可以翻看前后篇,系统的学习一下.
方法三:
说了这么多,老赖的粉丝都等急了吧,哈哈,别说话,先那啥…..呃,上效果图呗!
看了效果图,有好朋友说,搞什么啊,跟上面不是一毛一样的么?还没有人家的360°旋转切换文字呢!!
咳咳,那不是重点好么,重点是切换下一张图片,是有视差效果!!!视差效果!!!视差效果!!
一张图片压着另一张图片上面,这个效果在iPhone里就有,好像是调用系统相册里面切换照片时候的效果.
另外,重点来了!!!无论你多少张照片,老赖我这里只有用了两个UIImageView!没错,就是两个,一样完成无限轮播!
这个*不能装过咯,老赖我还是低调的,其实思路也很清晰,接下来,就听有北京著名赖人—-老赖娓娓道来之:
首先咱们还是先声明一些属性
有好朋友打眼一看,就知道老赖不专业了,整两张图片的ImageView,命名竟然用first和second这low的名字.好吧,老赖承认,时间紧,任务重,各种原因吧,总之就这样了,爱咋咋地,跟老赖讲道理,嗯哼?
接下来就是对对象的初始化,老赖给代码都注释了
.
其实老赖不喜欢,贴这么多代码…好多好朋友都跟老赖一样,代码一多,看不下去.那老赖我就把重要部分的代码,简短的贴出来,并解释说明之,最后,会把源码地址贴出来.
这里要说明一下刚才那一长串代码,scrollView的contentSize是3个屏幕宽,并且初始让scrollView的可视部分在最中间, 正好可以用来左右滚动.
然后,第一张图片的放到最中间,并且,它的位置是固定的,也就是说,第一张图片跟随scrollView滚动.
那第二张图片,就扮演滑动图片后,将要出现的视图了.
首先假定我们手指,从左往右滑动,也就是看看左边的图片,就是上一张图片:
.
上面的代码是用来干嘛的呢?有好朋友一样就看出来了!对,就是让第二张图片跟随第一张图片也就是scrollView移动的:
.
那有好朋友要问了,为什么第二张图片的中心点的计算,用后面的那个等式呢?
这里简要解释一下视差的效果实现原理:
当第一张图片将要滚动的时候,第二章图片其实已经有一半在我们屏幕上.然后随着第一张图片移动,第一张图片移动一横屏,让第二章图片跟着移动半屏的距离就行了!
But!!真的是老赖上面说的那样吗?其实不是!不要轻易相信老赖!
之所以说不是,是因为假设第一张图片往右走,如果你让第二张图片也往右走,松开手后,效果完全不是这样.这里其实是让第二张图像左走.
对,相对于scrollView来说,第二章图片要向左走!为什么呢?因为整个scrollView都向右走,松手后,scrollView的可视位置,由中间变成了最左边,此时只有让第二章图片也出现在最左边也能完全展示出来它.第二张图片的初始位置是在一半屏幕宽度上的,所以它要往左走到零!
接着来说,图片加载相关.之前声明了如下的成员变量:
.
当视图滚动后,直接可以通过下一张图片的下标从数据源里取图片
.
然后,滚动,滚动,滚动,当图片是最后一张,再往后滚,或者当图片第一张,再往前滚的时候,就需要轮播,思想还是跳转:
.
实现了图片的轮播加载后,可能有细心的好朋友们,一直疑问着呢…你scrollView只有三个屏幕的宽度,只能往左滚动一次,怎么实现轮播呢?
估计问这个问题的好朋友,没有细心看方法一,不错,这里也要让scrollView瞬间跳转!只不过,这里无论往左还是往右,scrollView跳转的位置都是最中心!也就是重新回到原来的位置.不过这里特别需要注意的是:在跳转回之前,一定要把中间位置上的第一张图片,设置成现在第二张图片,这样视觉上才不会有跳跃!
.
看到这里,想必你大概也明白了这个视差轮播,以及只用两个UIImageView就能无限轮播的原理了吧!
那老赖也不卖关子了,把源码放上来吧:另外说一下,这里封装了两个,一个是代理协议回调的,一个是Block回调的,好朋友们各取所需吧:
https://github.com/wswei99/WSWscrollView
下面讲的是一些基本用法,demo里面的用例已经足够了,聪明的好朋友们,不用往下看了,帅的小伙伴们继续跟着老赖往下走吧!
先说说协议代理封装的:
.
使用这个轮播器,要遵循两个协议,并且必须实现一个方法:传入图片数组.
这里说明一下,图片数组不用你来区分本地还是网络图片了,老赖帮你判断了.
本地图片的话,你就传入照片名字的数组,别忘了jpg的要在名字后面加上.jpg哦!
网络图片的话,就传网络图片地址的字符串就行!
点击事件回调,会传过来一个图片的位置,你拿着这个位置下标,就可以进行其他操作了!
另外这里还有可调节时间计时器,手动销毁计时器,和手动开启计时器的外部接口,方便你自己添加功能或者项目需求吧;
再来说说Block封装的:
.
调用这个方法,传入图片源数组,然后手写回调block方法就可以了,下面是demo中的例子,可以看一眼:
.
哎呦,终于写完啦,iOS开发自学的课程还得继续更新,好了,老赖整理资料去了,收工!
封装好的Demo:https://github.com/wswei99/WSWScrollView
首先说,轮播图,这个东西,做开发的应该都会,不过实现的的逻辑思路有所不同.
方法一
比方说固定有5张图,最基本的实现方法就是,在scrollView上添加7张图片,排列方式是:
五一二三四五一
当图片滑到最左边,也就是”五”这个图片的时候,让scrollView调用setContentOffset 这个方法,直接跳转到倒数第二个张上面,也是”五”,所以肉眼是看不出scrollView移动的.
注意这里的跳,不能开启动画.同理,当scrollView滑到最后一个,让它瞬间跳到左边的”一”这张上去…这样就实现了无限循环滚动.
这个方法,非常巧妙,平面理解有点儿费劲,不过老赖理解之—>你拿张纸条,让它收尾相连,形成一个空间的圆圈闭环,这样,估计你瞬间里明白了这个瞬间跳转是怎么回事了!
先来看看这种方法的效果图:如下
看了上面的效果图后,问题也就出来了,这里有少量的图片,可以直接把图片的imageView加载到scrollView上.但是,如果图片多呢,50张?100张?创建100个imageView加到scrollView上,内存也吃不消吧.
对了,有好朋友,应该想到了,可以用–复用机制!
方法二:
复用机制的好处,在tableView用的淋漓尽致,做轮播图,咱们用它的亲戚,collectionView.因为系统空间本身就有复用机制,无论你加载多少照片,它只创建了两个cell,这样就大大的优化APP性能.
具体的详情,老赖这里不详细阐述了,照旧贴出相关链接:
http://www.cnblogs.com/wendingding/p/3890850.html
http://www.cnblogs.com/wendingding/p/3890953.html
这两篇是有关collectionView做轮播图的,当然,这是大神的系列,好朋友们,可以翻看前后篇,系统的学习一下.
方法三:
说了这么多,老赖的粉丝都等急了吧,哈哈,别说话,先那啥…..呃,上效果图呗!
看了效果图,有好朋友说,搞什么啊,跟上面不是一毛一样的么?还没有人家的360°旋转切换文字呢!!
咳咳,那不是重点好么,重点是切换下一张图片,是有视差效果!!!视差效果!!!视差效果!!
一张图片压着另一张图片上面,这个效果在iPhone里就有,好像是调用系统相册里面切换照片时候的效果.
另外,重点来了!!!无论你多少张照片,老赖我这里只有用了两个UIImageView!没错,就是两个,一样完成无限轮播!
这个*不能装过咯,老赖我还是低调的,其实思路也很清晰,接下来,就听有北京著名赖人—-老赖娓娓道来之:
首先咱们还是先声明一些属性
//滚动视图 @property (nonatomic, strong) UIscrollView *scrollView; //第一个图片 @property (nonatomic, strong) UIImageView *firstImageView; //第二个图片 @property (nonatomic, strong) UIImageView *secondImageView; //图片的数据源 @property (nonatomic, strong) NSMutableArray *imageDataSource; //页面控制器 @property (nonatomic, strong) UIPageControl *pageController; //时间控制器 @property (nonatomic, strong) NSTimer *timer;
有好朋友打眼一看,就知道老赖不专业了,整两张图片的ImageView,命名竟然用first和second这low的名字.好吧,老赖承认,时间紧,任务重,各种原因吧,总之就这样了,爱咋咋地,跟老赖讲道理,嗯哼?
接下来就是对对象的初始化,老赖给代码都注释了
//添加滚动视图 UIscrollView *scrollView = [[UIscrollView alloc] initWithFrame:self.bounds]; scrollView.showsHorizontalScrollIndicator = NO; scrollView.pagingEnabled = YES; scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.frame), 0); scrollView.delegate = self; scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.frame) * 3, CGRectGetHeight(self.frame)); //添加点击事件 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapClick:)]; [scrollView addGestureRecognizer:tap]; //添加到父视图上 [self addSubview:scrollView]; self.scrollView = scrollView; //给滚动视图添加两个UIImageView UIImageView *firstImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; self.firstImageView = firstImageView; UIImageView *secondImageView = [[UIImageView alloc] initWithFrame:self.bounds]; self.secondImageView = secondImageView; [self.scrollView addSubview:secondImageView]; [self.scrollView addSubview:firstImageView]; //先设置第一张图片的位置,在滚动视图的正中央 self.firstImageView.frame = CGRectMake(CGRectGetWidth(self.frame), 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)); //设置pageController(这里可以根据个人喜好自定义) UIPageControl *pageController = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), 20)]; pageController.center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) - 20); //设置pageController 的页数 pageController.numberOfPages = self.imageDataSource.count; pageController.currentPage = 0; [self addSubview:pageController]; self.pageController = pageController;
.
其实老赖不喜欢,贴这么多代码…好多好朋友都跟老赖一样,代码一多,看不下去.那老赖我就把重要部分的代码,简短的贴出来,并解释说明之,最后,会把源码地址贴出来.
这里要说明一下刚才那一长串代码,scrollView的contentSize是3个屏幕宽,并且初始让scrollView的可视部分在最中间, 正好可以用来左右滚动.
然后,第一张图片的放到最中间,并且,它的位置是固定的,也就是说,第一张图片跟随scrollView滚动.
那第二张图片,就扮演滑动图片后,将要出现的视图了.
首先假定我们手指,从左往右滑动,也就是看看左边的图片,就是上一张图片:
//添加将要出现的视图(其实就是第二张图片)的中心点X坐标 static float nextImageViewCenterX = 0.f; //判断滚动方向 if (scrollView.contentOffset.x < CGRectGetWidth(self.frame)) { //从左往右 nextImageViewCenterX = (CGRectGetWidth(self.frame) + offsetX) / 2; _nextImageIndex = _currentImageIndex - 1; }
.
上面的代码是用来干嘛的呢?有好朋友一样就看出来了!对,就是让第二张图片跟随第一张图片也就是scrollView移动的:
GPoint center = CGPointMake(nextImageViewCenterX , CGRectGetHeight(self.frame)/2); //实时更新第二张图片的位置 self.secondImageView.center = center ;
.
那有好朋友要问了,为什么第二张图片的中心点的计算,用后面的那个等式呢?
这里简要解释一下视差的效果实现原理:
当第一张图片将要滚动的时候,第二章图片其实已经有一半在我们屏幕上.然后随着第一张图片移动,第一张图片移动一横屏,让第二章图片跟着移动半屏的距离就行了!
But!!真的是老赖上面说的那样吗?其实不是!不要轻易相信老赖!
之所以说不是,是因为假设第一张图片往右走,如果你让第二张图片也往右走,松开手后,效果完全不是这样.这里其实是让第二张图像左走.
对,相对于scrollView来说,第二章图片要向左走!为什么呢?因为整个scrollView都向右走,松手后,scrollView的可视位置,由中间变成了最左边,此时只有让第二章图片也出现在最左边也能完全展示出来它.第二张图片的初始位置是在一半屏幕宽度上的,所以它要往左走到零!
接着来说,图片加载相关.之前声明了如下的成员变量:
//记录当前图片下标 int _currentImageIndex; //记录下一张图片下标 int _nextImageIndex;
.
当视图滚动后,直接可以通过下一张图片的下标从数据源里取图片
self.secondImageView.image = self.imageDataSource[_nextImageIndex];
.
然后,滚动,滚动,滚动,当图片是最后一张,再往后滚,或者当图片第一张,再往前滚的时候,就需要轮播,思想还是跳转:
if (_nextImageIndex == -1) { _nextImageIndex = (int)self.imageDataSource.count - 1; }else if (_nextImageIndex == self.imageDataSource.count){ _nextImageIndex = 0; }
.
实现了图片的轮播加载后,可能有细心的好朋友们,一直疑问着呢…你scrollView只有三个屏幕的宽度,只能往左滚动一次,怎么实现轮播呢?
估计问这个问题的好朋友,没有细心看方法一,不错,这里也要让scrollView瞬间跳转!只不过,这里无论往左还是往右,scrollView跳转的位置都是最中心!也就是重新回到原来的位置.不过这里特别需要注意的是:在跳转回之前,一定要把中间位置上的第一张图片,设置成现在第二张图片,这样视觉上才不会有跳跃!
// 减速完成(分页滑动是会减速的) - (void)scrollViewDidEndDecelerating:(UIscrollView *)scrollView { [self endRollscrollViewWith:scrollView]; } // 滑动动画结束 setContentOffset: animated:YES 动画结束调用 - (void)scrollViewDidEndScrollingAnimation:(UIscrollView *)scrollView{ [self endRollscrollViewWith:scrollView]; } //结束滚动后,重置页面 -(void)endRollscrollViewWith:(UIscrollView *)scrollView { //判断是否完成翻页 if (scrollView.contentOffset.x != CGRectGetWidth(self.frame)) { //更新当前图片下标 _currentImageIndex = _nextImageIndex; //给第一张相框添加图片 self.firstImageView.image = self.imageDataSource[_currentImageIndex]; //让视图瞬间回到中间位置 [self.scrollView setContentOffset:CGPointMake(CGRectGetWidth(self.frame), 0)]; //更新page self.pageController.currentPage = _currentImageIndex; } }
.
看到这里,想必你大概也明白了这个视差轮播,以及只用两个UIImageView就能无限轮播的原理了吧!
那老赖也不卖关子了,把源码放上来吧:另外说一下,这里封装了两个,一个是代理协议回调的,一个是Block回调的,好朋友们各取所需吧:
https://github.com/wswei99/WSWscrollView
下面讲的是一些基本用法,demo里面的用例已经足够了,聪明的好朋友们,不用往下看了,帅的小伙伴们继续跟着老赖往下走吧!
先说说协议代理封装的:
@property (nonatomic, assign) id<WSWscrollViewDelegate> delegate; @property (nonatomic, assign) id<WSWscrollViewDataSource> dataSource; //@required //给轮播视图提供数据源数组 - (NSArray *)imagesArrayForWSWscrollView:(WSWscrollView *)scrollView; //@optional //点击事件回调 - (void)wswScroView:(WSWscrollView *)scrollView didSelectRowAtIndexPath:(NSInteger)index;
.
使用这个轮播器,要遵循两个协议,并且必须实现一个方法:传入图片数组.
这里说明一下,图片数组不用你来区分本地还是网络图片了,老赖帮你判断了.
本地图片的话,你就传入照片名字的数组,别忘了jpg的要在名字后面加上.jpg哦!
网络图片的话,就传网络图片地址的字符串就行!
点击事件回调,会传过来一个图片的位置,你拿着这个位置下标,就可以进行其他操作了!
另外这里还有可调节时间计时器,手动销毁计时器,和手动开启计时器的外部接口,方便你自己添加功能或者项目需求吧;
再来说说Block封装的:
/** * 传入照片,并返回图片点击的回调block * * @param imagesArray 传入本地图片或者网络图片 * @param currentImageClickBlock 图片点击的block方法 */ - (void)addImagesArray:(NSArray *)imagesArray currentImageClick:(CurrentImageClick)currentImageClickBlock;
.
调用这个方法,传入图片源数组,然后手写回调block方法就可以了,下面是demo中的例子,可以看一眼:
//调用方法-->就是直接创建一个对象 WSWscrollView *scrollView = [[WSWscrollView alloc] initWithFrame:self.view.bounds]; /* 时间间隔一定要写在调用下面方法之前,因为方法里调用了创建时间控制器, 之后再设置间隔时间的话,就没有作用了 */ scrollView.timeInterval = 1.f; NSArray *array = @[@"火影01",@"火影02",@"火影03",@"火影04",]; //传入图片源数组并且实现回调block方法 [scrollView addImagesArray:array currentImageClick:^(NSInteger index) { NSLog(@"--->我点的这是第%ld张图片",(long)index); }]; //添加带父视图上 [self.view addSubview:scrollView];
.
哎呦,终于写完啦,iOS开发自学的课程还得继续更新,好了,老赖整理资料去了,收工!
封装好的Demo:https://github.com/wswei99/WSWScrollView
相关文章推荐
- 广搜 — — ZOJ 1649 Rescue
- data-options的移除验证(easyui validatebox中移除验证)
- AndroidStudio导入项目一直卡在Building gradle project info最快速解决方案
- C#中三层架构UI、BLL、DAL、Model实际操作
- iframe页面改动parent页面的隐藏input部件value值,不能触发change事件。
- chrome显示ue-editor上传的视频问题
- ORA-02266: unique/primary keys in table referenced by enabled foreign keys
- ANDROID L - Material Design详解(UI控件)
- No mapping found for HTTP request with URI [/exam3/welcome] in DispatcherServlet
- media query ie8- 兼容实现总结
- HOJ 1603 Brackets Sequence
- Request failed: unacceptable content-type: text/html
- Implement Queue using Stacks
- IOS开发-NSNumber、NSValue、NSData的区别
- SQL UNIQUE 约束
- 提取循环中包含continue的语句封装成方法
- bluez 协议栈实现3 应用层的协议栈实现分析之glib
- java中线程队列BlockingQueue的用法
- 解决github push错误The requested URL returned error: 403 Forbidden while accessing
- codeforces Longest Increasing Subsequence