兩個imageView實現圖片輪播

前言

在很多的項目中,都會用到圖片輪播這個功能,如今網上關於圖片輪播的輪子也層出不窮,千奇百怪,筆者根據本身的思路,用兩個imageView也實現了圖片輪播,這裏給你們介紹筆者的主要思路以及大概步驟。git

輪播實現步驟

層級結構

最底層是一個UIView,上面有一個UIScrollView和UIPageControl,scrollView上有兩個UIImageView,imageView的寬高=scrollView的寬高=view的寬高github

圖1

輪播原理

假設輪播控件的寬爲x,高爲y,咱們設置scrollView的contentSize的寬度爲3x,而且讓scrollView在x方向偏移量爲x,即顯示中間內容web

scrollView.contentSize = CGSizeMake(3x, y);
    scrollView.contentOffset = CGPointMake(x, 0);

2

接下來使用代理方法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來監聽滾動結束,結束後,會變成如下兩種狀況:服務器

  • 左滾以後

圖3

  • 右滾以後

圖4

此時,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,也有可能既有本地圖片,又有網絡圖片,那麼該如何加載呢?

  1. 定義一個imageArr用來接收外界傳進來的數組(能夠是圖片,也能夠是網絡圖片路徑,能夠圖片和路徑混合)
  2. 定義一個images用來存儲圖片(只裝圖片).判斷外界傳進來的數組,若是是圖片,直接添加到images,若是是鏈接,先添加一張默認的佔位圖
  3. 定義一個imageDic用來緩存圖片的字典,key爲圖片URL
  4. 定義一個operationDic用來保存下載操做的字典,key爲圖片URL

圖片緩存策略(SDWebImage的思路)

下載圖片,先從緩存中取,若是有,則替換以前的佔位圖片,若是沒有,去沙盒中取,若是有,替換佔位圖片,並添加到緩存中,若是沒有,開啓異步線程下載

監聽圖片點擊

在實際開發中,一般輪播圖都有點擊圖片跳轉到對應的內容的操做,所以須要監聽圖片的點擊,提供兩種思路:

  • 經過block:

    1. 定義一個block給外界
    2. 打開currentImageView的用戶交互
    3. 給currentImageView添加一個點擊手勢
    4. 在點擊手勢響應方法裏面調用block,並傳入圖片所在的索引
  • 經過代理:

    1. 定義一個協議方法,設置一個代理屬性
    2. 打開currentImageView的用戶交互
    3. 給currentImageView添加一個點擊手勢
    4. 在點擊手勢響應方法裏面用代理調用協議方法,

結束語

上面是筆者實現輪播圖的思路以及部分代碼,須要源碼的請戳這裏,若是在使用中發現有bug,歡迎提出!若是以爲好用,記得獻上你的star哦!

相關文章
相關標籤/搜索