iOS 實現(xiàn)UIScrollView的無限輪播(原理)

同學(xué)們在寫需求的時候肯定會時常用到UIScrollView歹茶。而說到UIScrollView你弦,大家最先想到的肯定就是它上面的無限輪播功能燎孟。蘋果在UIScrollView上并沒有提供相應(yīng)的方法讓大家實現(xiàn)輪播,所以就需要通過代碼進行處理來實現(xiàn)旷偿。先上圖


無限輪播效果圖.gif

我先給大家講講其實現(xiàn)的原理:
我們假設(shè)用幾張圖片實現(xiàn)輪播效果爆侣。首先,我們需要打開UIScrollView的分頁滑動

/// 分頁滑動
_scrollView.scrollEnabled = YES;

它方便的幫助我們實現(xiàn)了輪播的效果茫负,然后就需要我們來實現(xiàn)“無限的”輪播乎赴。接下來,我們就需要擺放圖片了榕吼,在擺放圖片時需要注意,我們需要在第一張圖片的位置擺放最后一張圖片(可能有點懵哈原探,不過不要著急慢慢往下看)顽素,然后我們依次擺放圖片(從第一張到最后一張),最后在所有圖片的尾部我們再放上第一張圖片戈抄。這樣我們就多放了兩張圖片(分別在首尾多放了一張圖)。我把對應(yīng)的方法寫一下:

/// 將圖片放置在UIScrollView上
-(void)setupImage {
    /// 在UIScrollView的最前面添加一張圖片
    UIImageView *firstImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, self.scrollView.frame.size.height)];
    /// 圖片名是最后一張圖片
    firstImageView.image = [UIImage imageNamed:self.imageNameList.lastObject];
    [self.scrollView addSubview:firstImageView];
    
    /// 添加圖片
    for (NSInteger index = 0; index < self.imageNameList.count; index ++) {
        /// UIScrollView上的每一張圖片
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((index + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
        imageView.image = [UIImage imageNamed:self.imageNameList[index]];
        
        [self.scrollView addSubview:imageView];
        self.scrollView.contentSize = CGSizeMake((index + 2) * self.scrollView.bounds.size.width, 0);
    }
    
    /// 在UIScrollView的最后面添加一張圖片
    UIImageView *lastImageView = [[UIImageView alloc] initWithFrame:CGRectMake((self.imageNameList.count + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
    /// 圖片名是第一張圖片
    lastImageView.image = [UIImage imageNamed:self.imageNameList.firstObject];
    [self.scrollView addSubview:lastImageView];
    
    /// 設(shè)置UIScrollView的偏移量
    self.scrollView.contentSize = CGSizeMake((self.imageNameList.count + 2) * self.scrollView.bounds.size.width, 0);
    
    /// 設(shè)置UIScrollView的起始偏移距離(將第一張圖片跳過)
    self.scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
    
    /// 圖片總數(shù)
    self.pageControl.numberOfPages = self.imageNameList.count;
    self.pageControl.currentPage = 0;
}

其實,如果大家看到這里裸诽,應(yīng)該就會大致明白無線輪播的實現(xiàn)原理了。接下來就是最后一步嘱函,在UIScrollView的代理方法里面寫邏輯:判斷UIScrollView的偏移量埂蕊,當(dāng)其滑動到首位時(顯示的是最后一張圖片)疏唾,滑動停止函似,就把偏移量修改最后面圖片的位置上(倒數(shù)第二張)。同理撇寞,當(dāng)UIScrollView滑動到最后時(顯示的是第一張圖片),滑動停止牌废,就把偏移量修改到第一張圖片的位置上(正數(shù)第二張)啤握。

#pragma mark - UIScrollViewDelegate
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    /// 當(dāng)UIScrollView滑動到第一位停止時,將UIScrollView的偏移位置改變
    if (scrollView.contentOffset.x == 0) {
        scrollView.contentOffset = CGPointMake(self.imageNameList.count * kScreenWidth, 0);
        self.pageControl.currentPage = self.imageNameList.count;
    /// 當(dāng)UIScrollView滑動到最后一位停止時排抬,將UIScrollView的偏移位置改變
    } else if (scrollView.contentOffset.x == (self.imageNameList.count + 1)* kScreenWidth) {
        scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
        self.pageControl.currentPage = 0;
    } else {
        self.pageControl.currentPage = scrollView.contentOffset.x / kScreenWidth - 1;
    }
}

ok畜埋,原理其實就是這樣。在首尾多加兩張圖片當(dāng)做占位符悠鞍,然后當(dāng)UIScrollView滑動到占位符的位置時模燥,改變UIScrollView的偏移量,簡單且方便蔫骂。下面就是全部代碼:

#import "ViewController.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width

@interface ViewController () <UIScrollViewDelegate>

/// 滑動控制器
@property (nonatomic, strong) UIScrollView *scrollView;
/// 圖片數(shù)組
@property (nonatomic, strong) NSArray<NSString *> *imageNameList;
/// 頁碼控制器
@property (nonatomic, strong) UIPageControl *pageControl;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 設(shè)置圖片名的數(shù)組
    self.imageNameList = @[@"image0", @"image1", @"image2", @"image3"];
    
    // 添加圖片
    [self setupImage];
}

/// 將圖片放置在UIScrollView上
-(void)setupImage {
    /// 在UIScrollView的最前面添加一張圖片
    UIImageView *firstImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, self.scrollView.frame.size.height)];
    /// 圖片名是最后一張圖片
    firstImageView.image = [UIImage imageNamed:self.imageNameList.lastObject];
    [self.scrollView addSubview:firstImageView];
    
    /// 添加圖片
    for (NSInteger index = 0; index < self.imageNameList.count; index ++) {
        /// UIScrollView上的每一張圖片
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((index + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
        imageView.image = [UIImage imageNamed:self.imageNameList[index]];
        
        [self.scrollView addSubview:imageView];
        self.scrollView.contentSize = CGSizeMake((index + 2) * self.scrollView.bounds.size.width, 0);
    }
    
    /// 在UIScrollView的最后面添加一張圖片
    UIImageView *lastImageView = [[UIImageView alloc] initWithFrame:CGRectMake((self.imageNameList.count + 1) * kScreenWidth, 0, kScreenWidth, self.scrollView.frame.size.height)];
    /// 圖片名是第一張圖片
    lastImageView.image = [UIImage imageNamed:self.imageNameList.firstObject];
    [self.scrollView addSubview:lastImageView];
    
    /// 設(shè)置UIScrollView的偏移量
    self.scrollView.contentSize = CGSizeMake((self.imageNameList.count + 2) * self.scrollView.bounds.size.width, 0);
    
    /// 設(shè)置UIScrollView的起始偏移距離(將第一張圖片跳過)
    self.scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
    
    /// 圖片總數(shù)
    self.pageControl.numberOfPages = self.imageNameList.count;
    self.pageControl.currentPage = 0;
}

#pragma mark - UIScrollViewDelegate
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    /// 當(dāng)UIScrollView滑動到第一位停止時浩嫌,將UIScrollView的偏移位置改變
    if (scrollView.contentOffset.x == 0) {
        scrollView.contentOffset = CGPointMake(self.imageNameList.count * kScreenWidth, 0);
        self.pageControl.currentPage = self.imageNameList.count;
    /// 當(dāng)UIScrollView滑動到最后一位停止時补胚,將UIScrollView的偏移位置改變
    } else if (scrollView.contentOffset.x == (self.imageNameList.count + 1)* kScreenWidth) {
        scrollView.contentOffset = CGPointMake(kScreenWidth, 0);
        self.pageControl.currentPage = 0;
    } else {
        self.pageControl.currentPage = scrollView.contentOffset.x / kScreenWidth - 1;
    }
}

#pragma mark - Get方法
-(UIScrollView *)scrollView {
    if (!_scrollView) {
        _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 200)];
        _scrollView.pagingEnabled = YES;
        _scrollView.clipsToBounds = NO;
        _scrollView.scrollEnabled = YES;
        _scrollView.delegate = self;
        _scrollView.bounces = NO;
        _scrollView.showsHorizontalScrollIndicator = NO;
        _scrollView.showsVerticalScrollIndicator = NO;
        
        [self.view addSubview:_scrollView];
    }
    
    return _scrollView;
}

-(UIPageControl *)pageControl {
    if (!_pageControl) {
        _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 150, kScreenWidth, 50)];
        
        _pageControl.userInteractionEnabled = NO;
        _pageControl.pageIndicatorTintColor = [UIColor blackColor];
        _pageControl.currentPageIndicatorTintColor = [UIColor grayColor];
        
        [self.view addSubview:_pageControl];
    }
    
    return _pageControl;
}

@end

好了溶其,如果大家使用的是swift語言,還可以參考這篇文章:http://www.reibang.com/p/0ba33e59a784

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓶逃,一起剝皮案震驚了整個濱河市廓块,隨后出現(xiàn)的幾起案子契沫,更是在濱河造成了極大的恐慌,老刑警劉巖浓利,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钞速,死亡現(xiàn)場離奇詭異,居然都是意外死亡渴语,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門牙甫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來调违,“玉大人,你說我怎么就攤上這事且轨⌒樾觯” “怎么了旋奢?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵至朗,是天一觀的道長剧浸。 經(jīng)常有香客問我锹引,道長唆香,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任初澎,我火速辦了婚禮,結(jié)果婚禮上软啼,老公的妹妹穿的比我還像新娘。我一直安慰自己祸挪,他們只是感情好贞间,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著整以,像睡著了一般。 火紅的嫁衣襯著肌膚如雪公黑。 梳的紋絲不亂的頭發(fā)上摄咆,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音吭从,去河邊找鬼朝蜘。 笑死涩金,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播熔吗,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼讼载!你這毒婦竟也來了中跌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤漩符,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后凸克,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡咐容,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年蚂维,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虫啥。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡孝鹊,死狀恐怖炊琉,靈堂內(nèi)的尸體忽然破棺而出又活,到底是詐尸還是另有隱情,我是刑警寧澤柳骄,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布耐薯,位于F島的核電站,受9級特大地震影響曲初,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜臼婆,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一颁褂、第九天 我趴在偏房一處隱蔽的房頂上張望故响。 院中可真熱鬧颁独,春花似錦、人聲如沸誓酒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捣染,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間榕栏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工扒磁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留式曲,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓兰伤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親敦腔。 傳聞我的和親對象是個殘疾皇子恨溜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容