思路
采用了最常見的方法,將所要展示的輪播圖放在UIScrollView上茵休,并將第一張加到最后手蝎,最后一張加到開頭棵介,以三張圖為例亏拉,如下圖:
輪播圖滑動到1s時及塘,將偏移量移動到1的位置笙僚,滑動到3s時肋层,將偏移量移動到3的位置栋猖,這個過程是沒有動畫的蒲拉,所以用戶看不出來燃领,這就實現(xiàn)輪播圖的循環(huán)滾動猛蔽。
代碼
1.自定義一個繼承UIView的HomeBannerView,當然灵寺,名字根據(jù)自己的喜好來定曼库。
定義了兩個常用的宏
#define VIEW_WIDTH self.bounds.size.width
#define VIEW_HEIGHT self.bounds.size.height
給HomeBannerView定義一些屬性,其中block回調實現(xiàn)輪播圖的點擊跳轉事件略板,banners中存放的模型凉泄,currentSelectedPage是當前的頁數(shù)。
@property (copy, nonatomic) void(^block)(NSInteger);
@property (strong, nonatomic) NSMutableArray *banners;
@property (strong, nonatomic) UIScrollView *scrollView;
@property (strong, nonatomic) UIPageControl *pageControl;
@property (assign, nonatomic) NSUInteger currentSelectedPage;
@property (strong, nonatomic) NSTimer *timer;
- (void)loadData;
重寫HomeBannerView的initWithFrame:函數(shù)蚯根,調用設置UI的函數(shù)后众。
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame: frame]) {
[self setupUI];
}
return self;
}
設置UI:設置scrollView和pageControl的基本屬性,并給scrollView添加單擊手勢颅拦。
- (void)setupUI {
// 設置scrollView
self.scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.pagingEnabled = YES;
self.scrollView.bounces = NO;
self.scrollView.delegate = self;
[self addSubview:self.scrollView];
// 設置pageControl
self.pageControl = [[UIPageControl alloc] init];
self.pageControl.userInteractionEnabled = NO;
[self addSubview:self.pageControl];
[self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.mas_centerX);
make.bottom.mas_equalTo(self);
}];
// 添加單擊手勢
UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)];
tapGestureRecognize.delegate = self;
tapGestureRecognize.numberOfTapsRequired = 1;
[_scrollView addGestureRecognizer:tapGestureRecognize];
}
設置定時器蒂誉,定時器事件中讓當前頁數(shù)+1,然后更改scrollView的偏移量距帅,這時就會調用scrollViewDidScroll:函數(shù)绍移。
- (void)setupTimer {
self.timer = [NSTimer timerWithTimeInterval:3.0 target:self selector:@selector(timerEvent) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
- (void)timerEvent {
_currentSelectedPage ++;
[_scrollView setContentOffset:CGPointMake(VIEW_WIDTH * (_currentSelectedPage + 1), 0) animated:YES];
}
加載請求到的數(shù)據(jù)瞬测,這里也可以寫成帶參函數(shù),將模型數(shù)組傳進來。
- (void)loadData {
// 移除之前視圖
for (UIView *subView in _scrollView.subviews) {
if ([subView isKindOfClass:[UIImageView class]]) {
[subView removeFromSuperview];
}
}
if (self.banners.count == 0) {
// 顯示默認頁问潭,無數(shù)據(jù)頁面
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, VIEW_WIDTH, VIEW_HEIGHT)];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.image = [UIImage imageNamed:@""]; // 設置默認圖片
[_scrollView addSubview:imageView];
return;
}
_pageControl.numberOfPages = self.banners.count;
_pageControl.currentPage = 0;
// 這里就是前文提到的,首尾各添加一張圖片
[self.banners insertObject:self.banners.lastObject atIndex:0];
[self.banners addObject:[self.banners objectAtIndex:1]];
_scrollView.contentSize = CGSizeMake(VIEW_WIDTH * self.banners.count, VIEW_HEIGHT);
for (NSInteger i = 0; i < self.banners.count; i ++) {
CGRect imgRect = CGRectMake(VIEW_WIDTH * i, 0, VIEW_WIDTH, VIEW_HEIGHT);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imgRect];
BannerModel *banner = self.banners[i];
[imageView sd_setImageWithURL:[NSURL URLWithString:banner.image_path]];
[_scrollView addSubview:imageView];
}
if (self.banners.count > 1) {
_scrollView.contentOffset = CGPointMake(VIEW_WIDTH, 0);
} else {
_scrollView.contentOffset = CGPointZero;
}
// 最開始setupTimer添加到initWithFrame:函數(shù)中竖螃,這樣當banners.count == 0的時候,也會調用定時器,就會偏移到一片空白,放在這里比較合理蜜另。
[self setupTimer];
}
scrollView滾動時調用這個方法嘶居,在這里判斷偏移量,在這里實現(xiàn)前文思路中提到的1s變1,3s變3的過程炸客。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat targetX = scrollView.contentOffset.x;
if (self.banners.count >= 3) {
if (targetX >= VIEW_WIDTH * (self.banners.count - 1)) {
targetX = VIEW_WIDTH;
} else if (targetX <= 0) {
targetX = VIEW_WIDTH * (self.banners.count - 2);
}
_scrollView.contentOffset = CGPointMake(targetX, 0);
}
NSInteger page = (scrollView.contentOffset.x + VIEW_WIDTH * 0.5) / VIEW_WIDTH;
if (self.banners.count > 1) {
page--;
if (page >= _pageControl.numberOfPages) {
page = 0;
} else if (page < 0) {
page = _pageControl.numberOfPages - 1;
}
}
_currentSelectedPage = page;
_pageControl.currentPage = page;
}
開始拖動的時候關閉定時器开仰,結束拖動的時候開啟定時器。
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 關閉定時器
[self.timer invalidate];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// 開啟定時器
[self setupTimer];
}
scrollView的點擊事件,通過block來實現(xiàn)頁面的跳轉,根據(jù)偏移量判斷當前點擊的是第幾個輪播圖蟆炊。
- (void)singleTapGestureRecognizer:(UITapGestureRecognizer *)tapGesture {
NSInteger page = (NSInteger)(_scrollView.contentOffset.x / VIEW_WIDTH);
self.block(page);
}
2.接下來的方法是在控制器中實現(xiàn)的
將bannerView添加到控制器中昧甘。
self.bannerView = [[HomeBannerView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, bannerHeight)];
[self.view addSubview:_bannerView];
__weak HomeViewController *weakSelf = self;
self.bannerView.block = ^(NSInteger page){
// 跳轉界面的代碼寫這里
};
在請求到數(shù)據(jù)之后給bannerView的banners賦值浇冰,然后調用bannerView的loadData函數(shù)。
self.bannerView.banners = 請求到的數(shù)據(jù);
[self.bannerView loadData];
這樣輪播圖的功能就實現(xiàn)了罪塔。