忙碌的工作终于开始有了闲暇,现在无事,整理一下我在项目中我个人觉的遇到的经典的而且非常容易受用的小例子。今天说的就是这广告位(banner图)顺时针自动轮播的问题,下面先来说一下其实现原理(我以3张图为例):
1)首先我们拿到数据后,确定其中图片的个数
2)拿到图片的数组,不要急着直接使用,要重新将数组里面的数据放到一个MutableArray里面
3)如何放置:(1)将得到数组的最后的一个对象array[count-1]放在MutableArray第一个位置(2)然后将得到的数组Array整个放到MutableArray里面(3)最后将得到的数组Array[0]的第1个元素添加到MutableArray的最后;这样我们由原来数组的3个对象变成5个对象了
4)用重新得到的数组的元素个数创建scrollView的contentSize;注意:创建pagecontrol的时候还是使用原来数组的count
原理说到这里:下面贴上我写的demo代码
#import "ViewController.h"
#define kScreenW [UIScreen mainScreen].bounds.size.width
#define kImageHeight 150.0 //这个数根据美工那边的UI定
@interface ViewController ()<UIScrollViewDelegate> {
NSMutableArray *imageMutableArray;
}
@property (nonatomic, strong) NSArray *images;//放图片的数组
@property (nonatomic, strong) UIScrollView *bannerScrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.images = @[@"1.png", @"2.png", @"3.png"];
[self setupBannerView];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self startTimer];
}
/**
* 如果图片(url)是从服务器上得到的,这个setupBannerView方法要写在数据请求完成之后调用
*/
- (void)setupBannerView {
UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, 64, kScreenW, kImageHeight)];
bannerView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:bannerView];
//1、先将图片交换放入新数组
imageMutableArray = [NSMutableArray array];
//做一个安全判断,然后呼唤第一张和最后一张图片的位置
if (self.images.count > 1) {
//将最后一张图片放在数组的第一个位置
[imageMutableArray addObject:self.images[self.images.count - 1]];
//再将数组整个放到数组中
[imageMutableArray addObjectsFromArray:self.images];
//将数组的第一张图片放在新数组的最后一个位置
[imageMutableArray addObject:self.images[0]];
} else {
//如果数组就只有一张图片,就没有必要在滚动了
[imageMutableArray addObjectsFromArray:self.images];
}
//2、创建scrollView
NSUInteger pageCount = imageMutableArray.count;//拿到新的数组中图片数量
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, kScreenW, kImageHeight)];
scrollView.contentSize = CGSizeMake(kScreenW * pageCount, kImageHeight);//设置可滑动的宽度
scrollView.pagingEnabled = YES;
scrollView.delegate = self;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
//添加手势 可以进入到下一级
UITapGestureRecognizer *onceTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showBannerDetail)];
onceTapGesture.numberOfTapsRequired = 1;
[scrollView addGestureRecognizer:onceTapGesture];
self.bannerScrollView = scrollView;
[bannerView addSubview:self.bannerScrollView];
//设置开始启动的初始位置
[self.bannerScrollView setContentOffset:CGPointMake(kScreenW, 0) animated:NO];
//3、创建imageView并加载到scrollView上
for (int i = 0; i < pageCount; i ++) {
UIImageView *bannerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(kScreenW * i, 0, kScreenW, kImageHeight)];
NSString *imageName = [NSString stringWithFormat:@"%d.png", (i)];
bannerImageView.image = [UIImage imageNamed:imageName];
[scrollView addSubview:bannerImageView];
}
//4、pageControl
NSUInteger count = self.images.count;//指示器的数量要跟图片的数量保持一致
UIPageControl *pageCrl = [[UIPageControl alloc] initWithFrame:CGRectMake((kScreenW - 100) / 2.0, 64 + (kImageHeight - 20) / 2.0, 100, 10)];
pageCrl.numberOfPages = count;//指示器的页数
pageCrl.currentPage = 0;//显示当前为第一页
pageCrl.pageIndicatorTintColor = [UIColor redColor];
pageCrl.currentPageIndicatorTintColor = [UIColor whiteColor];
[pageCrl addTarget:self action:@selector(updateImage) forControlEvents:UIControlEventValueChanged];
[bannerView addSubview:pageCrl];
self.pageControl = pageCrl;
//到这里基本上算是完成了,如果使得banner更严谨,降低Crash的频率做一下安全判断
self.bannerScrollView.scrollEnabled = count > 1;
//开启定时器
if (count > 1) {
[self startTimer];
//将scrollView重新定在第一页位置
[self.bannerScrollView setContentOffset:CGPointMake(kScreenW, 0) animated:NO];//将动画设置为no,用来营造假象
} else {
[self.bannerScrollView setContentOffset:CGPointZero animated:NO];
}
}
- (void)startTimer {
if (self.timer)
[self.timer invalidate];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(updateImage) userInfo:nil repeats:YES];
self.timer = timer;
}
- (void)showBannerDetail {
NSUInteger currentPage = self.pageControl.currentPage;
NSLog(@"点击了%ld页", currentPage);
}
#pragma UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.timer invalidate];//当拖拽的时候,把定时器停掉。以避免Crash
self.timer = nil;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
[self startTimer];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
//修改Pages的当前页
if (scrollView == self.bannerScrollView) {
int index = scrollView.contentOffset.x / kScreenW;
if (index == 0) {
[self.bannerScrollView setContentOffset:CGPointMake(kScreenW * (imageMutableArray.count - 2), 0) animated:NO];
self.pageControl.currentPage = self.images.count - 1;
} else if (index == imageMutableArray.count - 1) {
[self.bannerScrollView setContentOffset:CGPointMake(kScreenW, 0) animated:NO];
self.pageControl.currentPage = 0;
} else {
self.pageControl.currentPage = index - 1;
}
}
}
- (void)updateImage {
NSInteger index = self.bannerScrollView.contentOffset.x / kScreenW;
//前面为了使轮播图向同一个方向滚动,在第一个位置放置的是最后的一个图片,所以正式的开始是从第二个位置开始的,这是为了给肉眼造成假象
index = (index + 1) % (self.images.count + 2);
if (index == self.images.count + 1) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.bannerScrollView setContentOffset:CGPointMake(kScreenW, 0) animated:NO];
});
}
[self.bannerScrollView setContentOffset:CGPointMake(index * kScreenW, 0) animated:YES];
//当显示的是第一张图的时候,指示器显示第一个
if (index == 0) {
self.pageControl.currentPage = self.images.count - 1;
} else if (index == self.images.count + 1) {
self.pageControl.currentPage = 0;
} else {
self.pageControl.currentPage = index - 1;
}
}
效果图:
代码是我看别人的博客后根据自己的理解想着写的,学习没有什么捷径,只能靠自己亲手写,才能理解其中的原理,上面的例子没有经过什么繁琐的封装,只是简单的广告轮播,另外,如果我写的代码有不足的地方欢迎指正。相互学习吧。