首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

iOS UIScrollView 實現無縫輪播圖(無限循環滾動)完整教程

     編輯:C++ 入門

基於 UIScrollView 的無縫輪播圖實現原理與代碼實戰

無縫輪播圖(Banner/Carousel)是 App 首頁常見組件。核心思路:在 UIScrollView 中佈局 N+2 張圖片(首尾各複製一張),利用 contentOffset 重置實現視覺上的無限循環。本文提供完整實現代碼並詳解關鍵邏輯。

核心佈局策略

  • 假設需展示 number 張圖片(如 4 張)
  • contentSize = (number + 2) * width:共 6 個頁面位置
  • 索引佈局:[最後一張][第1張][第2張][第3張][第4張][第1張複製]
  • 初始 contentOffset = (1 * width, 0):直接顯示真正的第 1 張

完整實現代碼

// MARK: - 初始化佈局
- (void)createView {
    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, 320, 230)];
    self.scrollView.backgroundColor = [UIColor yellowColor];
    self.scrollView.pagingEnabled = YES;
    self.scrollView.bounces = NO;
    self.scrollView.showsHorizontalScrollIndicator = NO;
    self.scrollView.delegate = self;
    self.scrollView.contentSize = CGSizeMake(320 * (number + 2), 240);

    // 佈局 N+2 個 UIImageView
    for (int i = 0; i < number + 2; i++) {
        UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(320 * i + 3, 3, 314, 224)];
        imgView.tag = 100 + i;
        imgView.userInteractionEnabled = YES;
        imgView.backgroundColor = [UIColor redColor];
        [self.scrollView addSubview:imgView];
    }

    // 初始偏移:顯示真正的第一張
    self.scrollView.contentOffset = CGPointMake(320, 0);
    [self.view addSubview:self.scrollView];
    
    [self addImage];       // 填充圖片
    [self setupPageControl]; // 頁碼指示器
    [self addTimer];       // 自動輪播定時器
}

// MARK: - 圖片填充邏輯(關鍵:首尾複製)
- (void)addImage {
    // 1. 填充中間真實圖片 (索引 1~number)
    for (int i = 0; i < number; i++) {
        UIImageView *iv = (UIImageView *)[self.scrollView viewWithTag:101 + i];
        iv.image = [UIImage imageNamed:self.imageNameArray[i]];
    }
    // 2. 首位複製最後一張 (索引 0)
    UIImageView *first = (UIImageView *)[self.scrollView viewWithTag:100];
    first.image = [UIImage imageNamed:self.imageNameArray[number - 1]];
    // 3. 尾位複製第一張 (索引 number+1)
    UIImageView *last = (UIImageView *)[self.scrollView viewWithTag:100 + number + 1];
    last.image = [UIImage imageNamed:self.imageNameArray[0]];
}

// MARK: - 頁碼控制器點擊響應
- (void)handlePageControlAction:(UIPageControl *)sender {
    CGPoint offset = CGPointMake(sender.currentPage * 320, 0);
    [self.scrollView setContentOffset:offset animated:YES];
}

// MARK: - 自動輪播定時器
- (void)addTimer {
    [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
}
- (void)runTimer {
    CGFloat x = self.scrollView.contentOffset.x;
    [self.scrollView setContentOffset:CGPointMake(x + 320, 0) animated:YES];
}

// MARK: - UIScrollViewDelegate:無縫循環核心邏輯
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat offsetX = scrollView.contentOffset.x;
    CGFloat pageWidth = 320;
    
    // 1. 滾動到「複製的最後一張」(索引 0) → 瞬間跳到真正的最後一張 (索引 number)
    if (offsetX == 0) {
        [scrollView setContentOffset:CGPointMake(pageWidth * number, 0) animated:NO];
    }
    // 2. 滾動到「複製的第一張」(索引 number+1) → 瞬間跳到真正的第一張 (索引 1)
    else if (offsetX == pageWidth * (number + 1)) {
        [scrollView setContentOffset:CGPointMake(pageWidth, 0) animated:NO];
    }
    
    // 3. 更新頁碼指示器 (扣除首偏移)
    self.pageControl.currentPage = (offsetX / pageWidth) - 1;
}

關鍵技術點深度解析

1. 為什麼需要 N+2 張圖片?

若只有 N 張,從最後一張滑到第一張時會出現「倒退」動畫;複製首尾各一張,配合 animated:NO 瞬間重置 contentOffset,用戶感知為平滑循環。

2. 定時器與手勢衝突處理

  • 用戶拖拽時應暫停定時器,scrollViewWillBeginDragging 中 invalidate,scrollViewDidEndDragging 中重啟
  • 頁面不可見時(如 viewDidDisappear)銷毀定時器防止內存洩漏

3. 內存優化建議

  • 圖片異步加載(SDWebImage/Kingfisher)
  • 大圖下採樣顯示,釋放不可见頁面圖片內存
  • 考慮使用 UICollectionView 復用機制替代 UIScrollView 手動佈局

4. Auto Layout 時代的適配

若使用 Masonry/SnapKit,約束寫法:

[imgView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.bottom.equalTo(self.scrollView);
    make.width.equalTo(self.scrollView);
    make.left.equalTo(self.scrollView.mas_left).offset(320 * i);
}];

總結

掌握「首尾複製 + contentOffset 瞬間重置 + delegate 監聽」三大核心,即可實現流暢無縫輪播。實際項目中建議封裝為通用 CycleScrollView 組件,支持圖片點擊回調、自定義頁碼樣式、網絡圖片加載等擴展功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved