思路
为了实现广告轮播页首尾无缝衔接,我们要在创建完原有图片的基础上在第一张图片前面创建imageView显示最后一张图片,在最后一张图片后面创建imageView显示第一张图片,这样在最后一张往后滑,第一张往前滑,然后再经过计算修改scrollView的contentOffset,就可以实现轮播页的 首尾无缝衔接。
具体实现
1,首先创建scrollView,这里使用懒加载进行创建
- (UIScrollView *)scrollView {
if (!_scrollView) {
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
//初始contentOffset为self.frame.size.width
scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);
//contentSize的width为图片的数量加2,因为头尾各多加了一张图片
scrollView.contentSize = CGSizeMake(self.frame.size.width*(_images.count+2), self.frame.size.height);
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.bounces = NO;
scrollView.delegate = self;
[self addSubview:scrollView];
_scrollView = scrollView;
}
return _scrollView;
}
2,懒加载创建imageView
- (void)createImageViews {
for (NSInteger i = 0; i < _images.count + 2; i++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width*i, 0, self.frame.size.width, self.frame.size.height)];
//创建self.images.count + 2个imageView,为了实现左右滑动无缝连接,除了正常的图片之外,在第一张之前加上最后一张,在最后一张后加上第一张
if (i == 0) {
imageView.image = _images[_images.count-1];
} else if (i == _images.count + 1) {
imageView.image = _images[0];
} else {
imageView.image = _images[i - 1];
}
[self.scrollView addSubview:imageView];
}
}
3,懒加载创建pageControl
- (UIPageControl *)pageControl {
if (!_pageControl) {
UIPageControl *pageControl = [[UIPageControl alloc] init];
pageControl.numberOfPages = self.images.count;
self.currentPage = 0;
pageControl.hidden = !self.isPageControlNeed;
pageControl.currentPage = self.currentPage;
CGSize pageControlSize = [pageControl sizeForNumberOfPages:self.images.count];
pageControl.frame = CGRectMake((self.frame.size.width - pageControlSize.width)/2, self.frame.size.height - 50, pageControlSize.width, pageControlSize.height);
[self addSubview:pageControl];
_pageControl = pageControl;
}
return _pageControl;
}
4,懒加载创建定时器,为了防止滑动界面的时候定时器停止,把定时器的mode设置成NSRunLoopCommonModes
- (NSTimer *)timer {
if (!_timer) {
//创建定时器前先删除,可以防止多次创建
[_timer invalidate];
//创建定时器
NSTimer *timer = [NSTimer timerWithTimeInterval:_timeInterval target:self selector:@selector(imageScroll) userInfo:nil repeats:YES];
//添加到当前RunLoop中,设置模式为NSRunLoopCommonModes,可以防止滑动界面的时候定时器停止
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
_timer = timer;
}
return _timer;
}
5,设置定时器的滚动动画,每次执行当前页面加一,在block里修改contentOffSet,执行动画,然后判断是否是最后一张图片,如果是,重设currentPage,contentOffset。
//滚动动画
- (void)imageScroll {
self.currentPage++;
//执行动画
[UIView animateWithDuration:self.scrollAnimateDuration animations:^{
self.scrollView.contentOffset = CGPointMake(self.frame.size.width*(_currentPage+1), 0);
}];
if (self.currentPage == self.images.count) {
self.currentPage = 0;
self.scrollView.contentOffset = CGPointMake(self.frame.size.width*(_currentPage+1), 0);
;
}
self.pageControl.currentPage = self.currentPage;
}
6,上面已经设定好自动滚动的功能,下面我们要考虑手动滑动的逻辑判断,首先我们要遵守UIScrollViewDelegate协议,然后实现其代理,在滑动结束后,判断当前坐标,然后修改currentPage,如果在最后一页或者第一页,则修改contentOffset
#pragma mark - UIScrollViewDelegate
//设置代理轮动完成后触发
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSInteger offSet = scrollView.contentOffset.x;
//判断是否为最后一页
if (offSet == self.frame.size.width*(self.images.count+1)) {
offSet = self.frame.size.width;
self.scrollView.contentOffset = CGPointMake(offSet, 0);
self.currentPage = 0;
}
//判断是否为第一页
else if (offSet == 0) {
offSet = self.frame.size.width*self.images.count;
self.scrollView.contentOffset = CGPointMake(offSet, 0);
self.currentPage = self.images.count - 1;
}
//其它情况
else {
self.scrollView.contentOffset = CGPointMake(offSet, 0);
self.currentPage = offSet/self.frame.size.width - 1;
}
self.pageControl.currentPage = self.currentPage;
}
到这里为止一个无缝衔接的广告滚动页就完成了,有任何疑问请留言
Github:https://github.com/tinybird00/ZSXScrollAdView