在很多的項目中,都會用到圖片輪播這個功能,如今網上關於圖片輪播的輪子也層出不窮,千奇百怪,筆者根據本身的思路,用兩個imageView也實現了圖片輪播,這裏給你們介紹筆者的主要思路以及大概步驟。git
最底層是一個UIView,上面有一個UIScrollView和UIPageControl,scrollView上有兩個UIImageView,imageView的寬高=scrollView的寬高=view的寬高github
假設輪播控件的寬爲x,高爲y,咱們設置scrollView的contentSize的寬度爲3x,而且讓scrollView在x方向偏移量爲x,即顯示中間內容web
scrollView.contentSize = CGSizeMake(3x, y); scrollView.contentOffset = CGPointMake(x, 0);
接下來使用代理方法scrollViewDidScroll來監聽scrollView的滾動,定義一個枚舉來記錄滾動的方向數組
typedef NS_ENUM(NSInteger, Direction) { DirectionNone = 1 << 0, DirectionLeft = 1 << 1, DirectionRight = 1 << 2 }; // 滾動方向 @property (nonatomic, assign) Direction direction; - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offX = scrollView.contentOffset.x; self.direction = offX > self.width ? DirectionLeft : offX < self.width ? DirectionRight : DirectionNone; }
重寫direction的setter方法,根據滾動方向來設置下一張圖片的顯示,若是是往左邊滾動,那麼下一張圖片的位置應該在右邊,若是是往右滾動,那麼下一張圖片的位置應該在左邊。(ps:此處應該注意滾動到第一張和最後一張的邊界狀況)緩存
#pragma mark - 設置滾動方向 - (void)setDirection:(Direction)direction { if (_direction == direction) return; _direction = direction; if (_direction == DirectionNone) return; if (_direction == DirectionRight) { // 若是是向右滾動 self.nextImageView.frame = CGRectMake(0, 0, self.width, self.height); self.nextIndex = self.currentIndex - 1; if (self.nextIndex < 0) self.nextIndex = _images.count - 1; }else if (_direction == DirectionLeft){ // 若是是向左邊滾動 self.nextImageView.frame = CGRectMake(CGRectGetMaxX(_currentImageView.frame), 0, self.width, self.height); self.nextIndex = (self.currentIndex + 1) % _images.count; } self.nextImageView.image = self.images[self.nextIndex]; }
經過代理方法scrollViewDidEndDecelerating來監聽滾動結束,結束後,會變成如下兩種狀況:服務器
此時,scrollView的偏移量爲0或者2x兩種狀況,咱們經過代碼再次將scrollView的偏移量設置爲x,而且將nextImageView的圖片修改成賦值給currentImageView的圖片網絡
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self pauseScroll]; } - (void)pauseScroll { // 等於1表示沒有滾動 if (self.scrollView.contentOffset.x / self.width == 1) return; self.currentIndex = self.nextIndex; self.pageControl.currentPage = self.currentIndex; self.currentImageView.frame = CGRectMake(self.width, 0, self.width, self.height); self.descLabel.text = self.describeArray[self.currentIndex]; self.currentImageView.image = self.nextImageView.image; self.scrollView.contentOffset = CGPointMake(self.width, 0); }
這樣以後,咱們看到的仍是currentImageView,只是圖片顯示的是下一張的圖片或者上一張的圖片,又回到了最初的樣子。異步
輪播的功能實現了,接下來就是添加定時器讓它自動滾動了。oop
// 開啓定時器 - (void)startTimer { // 若是隻有一張,直接放回,不須要開啓定時器 if (_images.count <= 1) return; // 若是定時器已經開啓,則先中止再開啓 if (self.timer) [self stopTimer]; self.timer = [NSTimer timerWithTimeInterval:_time < 1 ? DEFAULTTIME : _time target:self selector:@selector(nextPage) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; } // 下一頁 - (void)nextPage { [self.scrollView setContentOffset:CGPointMake(self.width * 2, 0) animated:YES]; }
setContentOffset:animated:方法執行完畢後不會調用scrollview的scrollViewDidEndDecelerating方法,可是會調用scrollViewDidEndScrollingAnimation方法,所以咱們要在該方法中調用pauseScrollatom
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { [self pauseScroll]; }
當咱們手動拖拽的時候,須要中止自動滾動,此時咱們只須要關閉定時器就好了,當咱們拖拽結束的時候,從新啓動定時器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self stopTimer]; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { [self startTimer]; }
在實際開發中,咱們不多自動輪播本地的圖片,大部分都是服務器獲取的圖片url,也有可能既有本地圖片,又有網絡圖片,那麼該如何加載呢?
下載圖片,先從緩存中取,若是有,則替換以前的佔位圖片,若是沒有,去沙盒中取,若是有,替換佔位圖片,並添加到緩存中,若是沒有,開啓異步線程下載
在實際開發中,一般輪播圖都有點擊圖片跳轉到對應的內容的操做,所以須要監聽圖片的點擊,提供兩種思路:
經過block:
- 定義一個block給外界
- 打開currentImageView的用戶交互
- 給currentImageView添加一個點擊手勢
- 在點擊手勢響應方法裏面調用block,並傳入圖片所在的索引
經過代理:
- 定義一個協議方法,設置一個代理屬性
- 打開currentImageView的用戶交互
- 給currentImageView添加一個點擊手勢
- 在點擊手勢響應方法裏面用代理調用協議方法,
上面是筆者實現輪播圖的思路以及部分代碼,須要源碼的請戳這裏,若是在使用中發現有bug,歡迎提出!若是以爲好用,記得獻上你的star哦!