@whiteiOS
2017-01-10T12:23:38.000000Z
字数 5664
阅读 1168
iOS学习之路
一共有3个imageView,初始化状态看到的是位于3个imageView中间的第一张图片,此时scrollView的contentOffsetX等于width,然后左边是最后一张图片,右边是第二张图片。如果用户向左滑动显示第二张图片,当第二张图片完全显示出来后,此时scrollView的contentOffsetX等于2*width,我们要做的第一件事就是将用户移动的位置进行复位,也就是让scrollView的contentOffsetX变回width,然后重新设置每个imageView应该显示的图片,因为代码执行速度很快,所以你意识不到它的切换。这样左边的imageView显示的是当前图片的上一张图片,右边的imageView显示的是当前图片的下一张图片,如下图所示

CXInfiniteScrollView.m中
(一)初始化添加子控件
//UIImageView的个数static NSUInteger const CXImageViewCout = 3;/** 初始化:添加子控件*/- (instancetype)initWithFrame:(CGRect)frame{if (self = [super initWithFrame:frame]) {_scrollInterval = 2.0;_animationInterval = 1.0;//添加scrollView对象UIScrollView *scrollView = [[UIScrollView alloc] init];scrollView.backgroundColor = [UIColor clearColor];scrollView.showsHorizontalScrollIndicator = NO;scrollView.showsVerticalScrollIndicator = NO;scrollView.pagingEnabled = YES;scrollView.delegate = self;scrollView.bounces = NO;[self addSubview:scrollView];self.scrollView = scrollView;//添加3个UIImageView对象for (NSUInteger i = 0; i < CXImageViewCout; i++) {UIImageView *imageView = [[UIImageView alloc] init];imageView.contentMode = UIViewContentModeScaleToFill;[scrollView addSubview:imageView];}//添加pageControl对象UIPageControl *pageControl = [[UIPageControl alloc] init];[self addSubview:pageControl];pageControl.currentPageIndicatorTintColor = [UIColor redColor];self.pageControl = pageControl;}return self;}
(二)布局子控件
/** 布局子控件*/- (void)layoutSubviews{[super layoutSubviews];//scrollViewself.scrollView.frame = self.bounds;//pageControlCGSize pageSize = [self.pageControl sizeForNumberOfPages:_imageNames.count];CGFloat pageControlX = (self.bounds.size.width - pageSize.width) / 2;CGFloat pageControlY = self.bounds.size.height - pageSize.height;self.pageControl.frame = CGRectMake(pageControlX, pageControlY, pageSize.width, pageSize.height);//imageViewCGFloat imageW = self.scrollView.frame.size.width;CGFloat imageH = self.scrollView.frame.size.height;for (NSUInteger i = 0; i < CXImageViewCout; i++) {UIImageView *imageView = self.scrollView.subviews[i];imageView.frame = CGRectMake(i * imageW, 0, imageW, imageH);}self.scrollView.contentOffset = CGPointMake(imageW, 0);self.scrollView.contentSize = CGSizeMake(imageW * CXImageViewCout, 0);}
(三)属性的set方法
/** 根据传入的图片数组设置图片*/- (void)setImageNames:(NSArray *)imageNames{_imageNames = imageNames;self.pageControl.numberOfPages = imageNames.count;//更新UIImageView内容[self updateContent];//开启定时器[self startTimer];}
注意:要在该方法中更新UIImageView内容,意思是获取到图片后接着更新UIImageView,之前在别的地方调用的updateContent,导致scrollView老是等好几秒才显示网络图片,弄了好久才发现是这的问题
(四)设置UIImageView的内容
/** 更新UIImageView内容*/- (void)updateContent{//从左到右重新设置每个imageView的图片内容for (NSUInteger i = 0; i < CXImageViewCout; i++) {UIImageView *imageView = self.scrollView.subviews[i];//为了设置imageView对应的图片索引NSInteger imageIndex = 0;if (i == 0) { //最左边的imageViewimageIndex = self.pageControl.currentPage - 1;} else if (i == 2) { //最右边的imageViewimageIndex = self.pageControl.currentPage + 1;} else {imageIndex = self.pageControl.currentPage;}//无限循环的处理if (imageIndex == -1) { //当上面的imageIndex为0时,如果再向右拖动,左侧图片显示,应该让它显示为最后一张图片imageIndex = self.imageNames.count - 1;} else if (imageIndex == self.imageNames.count) { //当上面的imageIndex超过最大图片数量时,也就是滑到最右再继续滑动的时候,让它显示第一张图片imageIndex = 0;}//判断是URL还是本地图片NSString *imageName = self.imageNames[imageIndex];if (imageName) {if ([self verifyURL:imageName]) {NSURL *url = [NSURL URLWithString:imageName];[imageView sd_setImageWithURL:url];} else {imageView.image = [UIImage imageNamed:imageName];}}//绑定图片索引到imageView的tagimageView.tag = imageIndex;}//scrollView的contentOffset(偏移量归位)self.scrollView.contentOffset = CGPointMake(self.scrollView.frame.size.width, 0);}/** 判断是否是URL*/- (BOOL)verifyURL:(NSString *)url{NSString *pattern = @"((http|ftp|https)://)(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?";NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];BOOL isMatch = [p evaluateWithObject:url];return isMatch;}
(五)scrollView代理方法的设置
/** 拖拽的时候*/- (void)scrollViewDidScroll:(UIScrollView *)scrollView{//拖动的时候,哪张图片最靠中间,也就是偏移量最小,就滑到哪页// imageView的x 和 scrollView偏移量x 的最小差值CGFloat minDelta = MAXFLOAT; //MAXFLOAT:最大浮点数// 找出显示在最中间的图片索引NSInteger centerImageIndex = 0;for (NSUInteger i = 0; i < CXImageViewCout; i++) {UIImageView *imageView = self.scrollView.subviews[i];// ABS : 取得绝对值CGFloat delta = ABS(imageView.frame.origin.x - self.scrollView.contentOffset.x);if (delta < minDelta) {minDelta = delta;centerImageIndex = imageView.tag;}}// 设置页码self.pageControl.currentPage = centerImageIndex;}/** 拖拽开始时停止定时器*/- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{[self stopTimer];}/** 拖拽结束时开启定时器*/- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{[self startTimer];}/** 减速停止的时候更新图片*/- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{[self updateContent];}
(六)设置定时器
/** 开启定时器*/- (void)startTimer{if (!_timer) {_timer = [NSTimer scheduledTimerWithTimeInterval:_scrollInterval target:self selector:@selector(nextPage) userInfo:nil repeats:YES];}}/** 停止定时器*/- (void)stopTimer{[self.timer invalidate];//计时器被系统强引用,必须手动释放self.timer = nil;}/** 显示下一页*/- (void)nextPage{[UIView animateWithDuration:_animationInterval animations:^{self.scrollView.contentOffset = CGPointMake(2 * self.scrollView.frame.size.width, 0);} completion:^(BOOL finished) {//更新视图[self updateContent];}];}
(七)对外的接口
@interface CXInfiniteScrollView : UIView@property (nonatomic, strong) NSArray *imageNames;/** 切换图片的时间间隔 */@property (nonatomic, assign) CGFloat scrollInterval;/** 切换图片动画的时长 */@property (nonatomic, assign) CGFloat animationInterval;@end
(八)外界调用
- (void)viewDidLoad {[super viewDidLoad];NSArray *images = @[@"001.jpg", @"002.jpg", @"003.jpg", @"004.jpg"];CXInfiniteScrollView *scroll = [[CXInfiniteScrollView alloc] initWithFrame:CGRectMake(0, 0, 375, 200)];scroll.imageNames = images;[self.view addSubview:scroll];}