// 基於ScrollView的輪播模塊,循環滾動 // ViewController.m // Slider-輪播-循環滾動版 // // Created by JamesXiang on 15/7/25. // Copyright (c) 2015年 JamesXiang. All rights reserved. // #import ViewController.h @interface ViewController ()@property (nonatomic, strong) UIScrollView *scrollView; @property (nonatomic, strong) UIPageControl *pageControl; @property (nonatomic, strong) NSTimer *timer; @property (nonatomic, assign) int pageIndex; @property (nonatomic, assign) int pageCount; @property (nonatomic, assign) double sliderWidth; @property (nonatomic, assign) double sliderHeight; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self loadSlider]; // 輪播總入口 } - (void)loadSlider { // 設置相關參數 [self setParams]; // 加載輪播容器 [self loadSliderContainer]; // 加載輪播內容 [self loadSliderItem]; // 加載輪播頁碼控制器 [self loadSliderPageControl]; // 輪播開始 [self sliderBegin]; } - (void)setParams { // 設置頁碼為0 self.pageIndex = 0; // 輪播內容個數為5 self.pageCount = 5; // 設置輪播器高度為160 self.sliderHeight = 160; // 設置輪播器寬度為屏幕寬度 self.sliderWidth = self.view.frame.size.width; } - (void)loadSliderContainer { UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, self.sliderWidth, self.sliderHeight)]; scrollView.delegate = self; scrollView.pagingEnabled = YES; scrollView.showsHorizontalScrollIndicator = NO; // 設置contentSize scrollView.contentSize = CGSizeMake(self.sliderWidth * (self.pageCount + 2), self.sliderHeight); // 設置初始offset,左右都可連續滾動的基礎 scrollView.contentOffset = CGPointMake(self.sliderWidth, 0); scrollView.backgroundColor = [UIColor whiteColor]; _scrollView = scrollView; [self.view addSubview:_scrollView]; } - (void)loadSliderItem { // 循環輪播原理: // 需要輪播的內容為 slider0,slider1,slider2,slider3,slider4 // scrollView中實際內容 slider4-b,slider0,slider1,slider2,slider3,slider4,slider0-b // 這樣構造的目的是當達到最前邊或者最後邊時能夠以自然滾動的方式過度到下一個頁面 // slider0-b的作用: // 當過度slider0-b時,修改scrollView的contentOffset,完成連續滾動 // 例:當滾動到slider4時,繼續滾動到slider0-b,滾動完畢,這時 // 通過修改contentOffset使scrollView把處於第一個位置的slider0顯示出來,然後繼續向右滾動至slider1,連續滾動 // slider4-b的作用: // 當完成一輪滾動時,重新回到slider0時,通過人工拖拽向右挪動手指,如果沒有slider4-b,則會導致無法拉動 // 有了slider4-b,就算向左拉動仍然會有內容顯示 // 具體的移動策略見 updateLocation 方法 for (int i = 0; i < self.pageCount + 2; i++) { UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(self.sliderWidth * i, 0, self.sliderWidth, self.sliderHeight)]; // 打開imageView的用戶交互開關,允許與用戶交互 [imgView setUserInteractionEnabled:YES]; [imgView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sliderClick)]]; if (i == 0) { imgView.image = [UIImage imageNamed:[NSString stringWithFormat:@slider%d.jpg, self.pageCount-1]]; }else if(i == self.pageCount + 1) { imgView.image = [UIImage imageNamed:@slider0.jpg]; }else { imgView.image = [UIImage imageNamed:[NSString stringWithFormat:@slider%d.jpg, i - 1]]; } [self.scrollView addSubview:imgView]; } } - (void)sliderClick { NSLog(@點擊事件...用戶點擊了第 %d 張圖片,請做出回應, self.pageIndex); } - (void)loadSliderPageControl { UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, self.sliderHeight, self.sliderWidth, 20)]; pageControl.numberOfPages = self.pageCount; pageControl.currentPage = self.pageIndex; _pageControl = pageControl; [self.view addSubview:_pageControl]; } - (void)sliderBegin { self.timer = [NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:@selector(changeSlider) userInfo:nil repeats:YES]; } - (void)changeSlider { self.pageIndex++; if (self.pageIndex == self.pageCount) { self.pageIndex = 0; } [UIView animateWithDuration:0.8 animations:^{ self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x + self.sliderWidth, 0); } completion:^(BOOL finished) { self.pageControl.currentPage = self.pageIndex; }]; // 更新頁面index和特殊位置位移 [self updateIndexAndSpecialLocation]; } // 代理方法,當開始手動拉拽時 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self.timer invalidate]; } // 代理方法,當手動拉拽滾動完畢後 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self updateIndexAndSpecialLocation]; self.pageControl.currentPage = self.pageIndex; [self sliderBegin]; } - (void)updateIndexAndSpecialLocation { int index = self.scrollView.contentOffset.x / self.sliderWidth; if (index == 0) { // 當目前顯示的是slider4-b頁面時 self.pageIndex = self.pageCount - 1; // 修改offset,使後邊的slider4顯示出來 self.scrollView.contentOffset = CGPointMake(self.sliderWidth * self.pageCount, 0); }else if(index == self.pageCount + 1) { // 當目前顯示的是slider0-b頁時 // 修改offset,使前邊的slider0顯示出來 self.scrollView.contentOffset = CGPointMake(self.sliderWidth, 0); self.pageIndex = 0; }else { self.pageIndex = index-1; } } @end