UIScrollView循环滚动图片
2015-08-18 16:42
465 查看
转载自 http://www.jianshu.com/p/aa73c273baf2
我们会经常用到循环滚动图片,包括定时滚动,点击触发事件。
以前所知道的循环滚动图片的方法是这样的。比如:一共5张图片,位置为1,2,3,4,5。
创建7个
将最后一张图片放到第一张图片前面,将第一张图片放到最后一张后面,位置为5,1,2,3,4,5,1。
最后一张图片滚动到第一张图片时,先从第二个图片5滚动到第二个图片1,滚动完之后把位置设置为第一个图片1。从后向前滚动同样的原理。
在
这样做的原因是从第二个图片5滚动到第二个图片1之后偏移量是
以前是那么用的,但是后来觉得这样比较占资源,也比较麻烦,现在是这样的,不管多少张图片只创建3个
从
当前数组根据当前位置取出3张图片,当前展示的图片的前一张和后一张。如果当前需要展示的图片是第一张,则当前数组中的3张图片为图片5、图片1、图片2。如果当前需要展示的图片是最后一张图片,则当前数组中的3张图片为图片4、图片5、图片1。
这样展示的图片是第2张图片,偏移量为
点击图片触发的事件通过代理传出当前的图片位置。
数据源
滚动视图。本来是不需要这个属性的,但是有个问题:如果图片正好滚动了一半app进入到后台,再次打开的时候是滚动到一半状态,滚动到下一张图片的时候就好了,所以把这个问题在
代理方法
重写
重写图片数组的
刷新图片的方法
获取图片
定时器的方法
viewController里面的代码
获取到的网络数据方法里,设置循环滚动图片的图片数组
代理方法回调
处理图片正好滚动了一半app进入到后台,再次打开的时候是滚动到一半状态的问题。
我们会经常用到循环滚动图片,包括定时滚动,点击触发事件。
以前所知道的循环滚动图片的方法是这样的。比如:一共5张图片,位置为1,2,3,4,5。
创建7个
imageView。
将最后一张图片放到第一张图片前面,将第一张图片放到最后一张后面,位置为5,1,2,3,4,5,1。
最后一张图片滚动到第一张图片时,先从第二个图片5滚动到第二个图片1,滚动完之后把位置设置为第一个图片1。从后向前滚动同样的原理。
在
scrollViewDidScroll的代理方法里面判断
scrollView.contentOffset.x>320*6-1,将
scrollView的偏移量设置为
320的位置,动画设置为
NO。
这样做的原因是从第二个图片5滚动到第二个图片1之后偏移量是
320*6,这个值是大于
320*6-1的,进入到
if语句,将
scrollView设置
320的位置,则就是第一个图片1的位置,这样就造成一个视觉差,是从最后一张图片滚动到第一张图片的。
以前是那么用的,但是后来觉得这样比较占资源,也比较麻烦,现在是这样的,不管多少张图片只创建3个
imageView。
从
viewController中取到图片数据源,创建当前需要展示的图片数组长度是3,当前展示的图片位置默认是0。
当前数组根据当前位置取出3张图片,当前展示的图片的前一张和后一张。如果当前需要展示的图片是第一张,则当前数组中的3张图片为图片5、图片1、图片2。如果当前需要展示的图片是最后一张图片,则当前数组中的3张图片为图片4、图片5、图片1。
这样展示的图片是第2张图片,偏移量为
320,滑动到下一张图片的时候,设置当前位置为1,设置当前数组图片为图片1、图片2、图片3,刷新UI,并且把
scrollView的偏移量设置为
320,即展示的图片永远在中间。
点击图片触发的事件通过代理传出当前的图片位置。
CycleScrollView.h中的代码
#import <UIKit/UIKit.h> @protocol CycleScrollViewDelegate; @interface CycleScrollView : UIView<UIScrollViewDelegate>
数据源
@property (nonatomic, strong) NSArray *imageArray;
滚动视图。本来是不需要这个属性的,但是有个问题:如果图片正好滚动了一半app进入到后台,再次打开的时候是滚动到一半状态,滚动到下一张图片的时候就好了,所以把这个问题在
viewController里面处理。
@property (nonatomic, strong) UIScrollView *scrollView; @property (nonatomic, weak) id<CycleScrollViewDelegate> delegate; @end
代理方法
@protocol CycleScrollViewDelegate <NSObject> - (void)cycleScrollView:(CycleScrollView *)cycleScrollView didSelectImageView:(NSInteger)index; @end
CycleScrollView.m中的代码
#import "CycleScrollView.h" #import "ImageModel.h" //图片model #import "UIImageView+WebCache.h" //SDWebImage设置网络图片 #define c_width (self.bounds.size.width+10) //两张图片之前有10点的间隔 #define c_height (self.bounds.size.height) @implementation CycleScrollView { UIPageControl *_pageControl; //分页控件 NSMutableArray *_curImageArray; //当前显示的图片数组 NSInteger _curPage; //当前显示的图片位置 NSTimer *_timer; //定时器 }
重写
init方法
- (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { //滚动视图 self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, c_width, c_height)]; self.scrollView.contentSize = CGSizeMake(c_width*3, 0); self.scrollView.contentOffset = CGPointMake(c_width, 0); self.scrollView.pagingEnabled = YES; self.scrollView.showsHorizontalScrollIndicator = NO; self.scrollView.delegate = self; [self addSubview:self.scrollView]; //分页控件 _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, c_height-30, self.bounds.size.width, 30)]; _pageControl.userInteractionEnabled = NO; _pageControl.hidesForSinglePage = YES; _pageControl.currentPageIndicatorTintColor = [UIColor redColor]; _pageControl.pageIndicatorTintColor = [UIColor grayColor]; [self addSubview:_pageControl]; //初始化数据,当前图片默认位置是0 _curImageArray = [[NSMutableArray alloc] initWithCapacity:0]; _curPage = 0; } return self; }
scrollView的代理方法
#pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { //如果scrollView当前偏移位置x大于等于两倍scrollView宽度 if (scrollView.contentOffset.x >= c_width*2) { //当前图片位置+1 _curPage++; //如果当前图片位置超过数组边界,则设置为0 if (_curPage == [self.imageArray count]) { _curPage = 0; } //刷新图片 [self reloadData]; //设置scrollView偏移位置 [scrollView setContentOffset:CGPointMake(c_width, 0)]; } //如果scrollView当前偏移位置x小于等于0 else if (scrollView.contentOffset.x <= 0) { //当前图片位置-1 _curPage--; //如果当前图片位置小于数组边界,则设置为数组最后一张图片下标 if (_curPage == -1) { _curPage = [self.imageArray count]-1; } //刷新图片 [self reloadData]; //设置scrollView偏移位置 [scrollView setContentOffset:CGPointMake(c_width, 0)]; } } //停止滚动的时候回调 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { //设置scrollView偏移位置 [scrollView setContentOffset:CGPointMake(c_width, 0) animated:YES]; }
重写图片数组的
set方法
- (void)setImageArray:(NSMutableArray *)imageArray { _imageArray = imageArray; //设置分页控件的总页数 _pageControl.numberOfPages = imageArray.count; //刷新图片 [self reloadData]; //开启定时器 if (_timer) { [_timer invalidate]; _timer = nil; } //判断图片长度是否大于1,如果一张图片不开启定时器 if ([imageArray count] > 1) { _timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerScrollImage) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] runMode:UITrackingRunLoopMode beforeDate:[NSDate date]]; } }
刷新图片的方法
- (void)reloadData { //设置页数 _pageControl.currentPage = _curPage; //根据当前页取出图片 [self getDisplayImagesWithCurpage:_curPage]; //从scrollView上移除所有的subview NSArray *subViews = [self.scrollView subviews]; if ([subViews count] > 0) { [subViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } //创建imageView for (int i = 0; i < 3; i++) { UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(c_width*i, 0, self.bounds.size.width, c_height)]; imageView.userInteractionEnabled = YES; [self.scrollView addSubview:imageView]; //设置网络图片 ImageModel *model = _curImageArray[i]; NSURL *url = [NSURL URLWithString:model.image_url]; [imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"placeholder_320x120.png"]]; //tap手势 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapImage:)]; [imageView addGestureRecognizer:tap]; } }
获取图片
- (void)getDisplayImagesWithCurpage:(NSInteger)page { //取出开头和末尾图片在图片数组里的下标 NSInteger front = page - 1; NSInteger last = page + 1; //如果当前图片下标是0,则开头图片设置为图片数组的最后一个元素 if (page == 0) { front = [self.imageArray count]-1; } //如果当前图片下标是图片数组最后一个元素,则设置末尾图片为图片数组的第一个元素 if (page == [self.imageArray count]-1) { last = 0; } //如果当前图片数组不为空,则移除所有元素 if ([_curImageArray count] > 0) { [_curImageArray removeAllObjects]; } //当前图片数组添加图片 [_curImageArray addObject:self.imageArray[front]]; [_curImageArray addObject:self.imageArray[page]]; [_curImageArray addObject:self.imageArray[last]]; }
定时器的方法
- (void)timerScrollImage { //刷新图片 [self reloadData]; //设置scrollView偏移位置 [self.scrollView setContentOffset:CGPointMake(c_width*2, 0) animated:YES]; }
tap图片的方法
- (void)tapImage:(UITapGestureRecognizer *)tap { //设置代理 if ([_delegate respondsToSelector:@selector(cycleScrollView:didSelectImageView:)]) { [_delegate cycleScrollView:self didSelectImageView:_curPage]; } }
dealloc方法
- (void)dealloc { //代理指向nil,关闭定时器 self.scrollView.delegate = nil; [_timer invalidate]; } @end
viewController里面的代码
#import "CycleScrollView.h" @interface RootViewController:BaseViewController<CycleScrollViewDelegate> @property (nonatomic, strong) CycleScrollView *imageScrollView; self.imageScrollView = [[CycleScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 120)]; self.imageScrollView.delegate = self; [headerView addSubview:self.imageScrollView];
获取到的网络数据方法里,设置循环滚动图片的图片数组
if ( [[resultDict objectForKey:@"big_image_list"] count] > 0) { self.imageArray = [resultDict objectForKey:@"big_image_list"]; self.imageScrollView.imageArray = self.imageArray; }
代理方法回调
#pragma mark - CycleScrollViewDelegate - (void)cycleScrollView:(CycleScrollView *)cycleScrollView didSelectImageView:(NSInteger)index { NSLog(@"点击了第%ld张图片",(long)index+1); ImageModel *model = self.imageArray[index]; }
处理图片正好滚动了一半app进入到后台,再次打开的时候是滚动到一半状态的问题。
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //设置图片循环滚动,如果偏移位置大于330,则设置为330 if (self.imageScrollView.scrollView.contentOffset.x > 330) { self.imageScrollView.scrollView.contentOffset = CGPointMake(330*2, 0); } }
相关文章推荐
- 黑马程序员_GUI
- GPUImage 滤镜头文件
- UIWindow介绍
- OC UIAlertView简化使用
- iOS-UIDynamic-UIKit
- 去哪网实习总结:用到的easyui组件总结(JavaWeb)
- 常识:UI行业常用名词及缩写定义
- JAVA 生成 UUID
- freemaker html页面获取map的key和value
- UITableViewCell drawRect画线在iOS7下不显示的问题
- 让UITableView的headerView或footerView跟随cell一起滚动
- java中StringBuilder、StringBuffer、String类之间的关系
- 排序检索B - List of Conquests
- iOS开发系列--UITableView全面解析
- hdoj 1509 Windows Message Queue
- iOS开发 -- UIViewContentMode各类型效果
- UIAlertView的基本用法
- 黑马程序员_String类型以及StringBuilder
- POJ 1986 DIstance Query LCA水题
- RequireJS Optimizer 的使用和配置