iOS基礎--輪播圖

上一篇已經介紹了UIScrollView的使用,並且簡單的寫了一個輪播圖的例子,但是上一篇中的輪播圖不能自動滾動,也不能循環輪播。今天有時間整理一下自動循環輪播的真正輪播圖實例。

循環輪播圖的原理

實現循環輪播的原理現在常用的有兩種:
1、創建n+2個滾動子視圖。在滾動到首尾時候進行轉換調整。
2、創建3個滾動子視圖,每次滾動結束進行圖片位置調整。
本實例代碼使用第二種方式,創建3個滾動子視圖。
廢話不多說,直接上代碼,在代碼中做了詳細的註釋。

自定義類CustomerView.h文件代碼

#import <UIKit/UIKit.h>

//聲明協議,給輪播圖的點擊添加一個代理
//這裏使用@class是因爲下面的代理方法需要使用到本類。
@class CustomerView;
@protocol CustomerViewDelegate<NSObject>
@optional
//代理方法 點擊圖片回調
- (void)customerView:(CustomerView *)view indexOfClickedImage:(NSInteger)index;
@end

@interface CustomerView : UIView

//傳入用於輪播圖的圖片數組
@property (nonatomic, copy)NSArray *images;

//pageControl顏色設置
@property (nonatomic, strong) UIColor *currentPageColor;
@property (nonatomic, strong) UIColor *pageColor;

//代理
@property (nonatomic, weak) id<CustomerViewDelegate> delegate;

@end

自定義類CustomerView.m文件代碼

#import "CustomerView.h"

//輪播圖創建的圖片數量
static const int imageCount = 3;

//準守UIScrollViewDelegate協議
@interface CustomerView ()<UIScrollViewDelegate>

//定義全局變量在後面的自動輪播方法中使用
@property (nonatomic, weak)UIScrollView *scrollView;
@property (nonatomic, weak)UIPageControl *pageControl;
//定時器,用於自動輪播
@property (nonatomic, weak)NSTimer *timer;

@end

@implementation CustomerView

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        //定義一個scrollView,最主要的輪播控件
        UIScrollView *scrollView = [[UIScrollView alloc] init];
        scrollView.delegate = self;
        //橫豎兩種滾輪都不顯示
        scrollView.showsVerticalScrollIndicator = NO;
        scrollView.showsHorizontalScrollIndicator = NO;
        //需要分頁
        scrollView.pagingEnabled = YES;
        //不需要回彈
        scrollView.bounces = NO;
        [self addSubview:scrollView];
        self.scrollView = scrollView;
        
        //在scrollView中添加三個圖片
        for (int i = 0;i < imageCount; i++) {
            UIImageView *imageView = [[UIImageView alloc] init];
            [scrollView addSubview:imageView];
        }
        //添加pageControl
        UIPageControl *pageControl = [[UIPageControl alloc] init];
        [self addSubview:pageControl];
        self.pageControl = pageControl;
    }
    
    return self;
}

//佈局子控件
- (void)layoutSubviews {
    [super layoutSubviews];
    //設置scrollView的frame
    self.scrollView.frame = self.bounds;
    
    CGFloat width = self.bounds.size.width;
    CGFloat height = self.bounds.size.height;
    //設置contentSize,不同輪播方向的時候contentSize是不一樣的
    //contentSize要放三張圖片
    self.scrollView.contentSize = CGSizeMake(width * imageCount, height);
    //設置三張圖片的位置,併爲三個圖片添加點擊事件
    for (int i = 0; i < imageCount; i++) {
        UIImageView *imageView = self.scrollView.subviews[i];
        //給圖片添加點擊手勢
        imageView.userInteractionEnabled = YES;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewClick:)];
        [imageView addGestureRecognizer:tap];
        //設置圖片大小,和View相同
        imageView.frame = CGRectMake(i * width, 0, width, height);
    }
    //設置contentOffset,顯示最中間的圖片
    self.scrollView.contentOffset = CGPointMake(width, 0);
    
    //設置pageControl的位置
    CGFloat pageW = 100;
    CGFloat pageH = 20;
    CGFloat pageX = width/2-50;
    CGFloat pageY = height - pageH;
    self.pageControl.frame = CGRectMake(pageX, pageY, pageW, pageH);
}

//設置pageControl的CurrentPageColor
- (void)setCurrentPageColor:(UIColor *)currentPageColor {
    _currentPageColor = currentPageColor;
    self.pageControl.currentPageIndicatorTintColor = currentPageColor;
}

//設置pageControl的pageColor
- (void)setPageColor:(UIColor *)pageColor {
    _pageColor = pageColor;
    self.pageControl.pageIndicatorTintColor = pageColor;
}

//根據傳入的圖片數組設置圖片
- (void)setImages:(NSArray *)images {
    _images = images;
    //pageControl的頁數就是圖片的個數
    self.pageControl.numberOfPages = images.count;
    //默認一開始顯示的是第0頁
    self.pageControl.currentPage = 0;
    //設置圖片顯示內容
    [self setContent];
    //開啓定時器
    [self startTimer];
    
}

//設置顯示內容
- (void)setContent {
    //設置三個imageBtn的顯示圖片
    for (int i = 0; i < self.scrollView.subviews.count; i++) {
        //取出三個imageView
        UIImageView *imageView = self.scrollView.subviews[i];
        //這個是爲了給圖片做索引用的
        NSInteger index = self.pageControl.currentPage;
        
        if (i == 0) { //第一個imageView,隱藏在當前顯示的imageView的左側
            index--; //當前頁索引減1就是第一個imageView的圖片索引
        } else if (i == 2) { //第三個imageView,隱藏在當前顯示的imageView的右側
            index++; //當前頁索引加1就是第三個imageView的圖片索引
        }
        //無限循環效果的處理就在這裏
        if (index < 0) { //當上面index爲0的時候,再向右拖動,左側圖片顯示,這時候我們讓他顯示最後一張圖片
            index = self.pageControl.numberOfPages - 1;
        } else if (index == self.pageControl.numberOfPages) { //當上面的index超過最大page索引的時候,也就是滑到最右再繼續滑的時候,讓他顯示第一張圖片
            index = 0;
        }
        imageView.tag = index;
        //用上面處理好的索引給imageView設置圖片
        imageView.image = self.images[index];
        
    }
}

//狀態改變之後更新顯示內容
- (void)updateContent {
    CGFloat width = self.bounds.size.width;
    [self setContent];
    //唯一跟設置顯示內容不同的就是重新設置偏移量,讓它永遠用中間的按鈕顯示圖片,滑動之後就偷偷的把偏移位置設置回去,這樣就實現了永遠用中間的按鈕顯示圖片
    //設置偏移量在中間
    self.scrollView.contentOffset = CGPointMake(width, 0);
}

#pragma mark - UIScrollViewDelegate
//拖拽的時候執行哪些操作
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    //拖動的時候,哪張圖片最靠中間,也就是偏移量最小,就滑到哪頁
    //用來設置當前頁
    NSInteger page = 0;
    //用來拿最小偏移量
    CGFloat minDistance = MAXFLOAT;
    //遍歷三個imageView,看那個圖片偏移最小,也就是最靠中間
    for (int i = 0; i < self.scrollView.subviews.count; i++) {
        UIImageView *imageView = self.scrollView.subviews[i];
        CGFloat distance = 0;
        distance = ABS(imageView.frame.origin.x - scrollView.contentOffset.x);
        if (distance < minDistance) {
            minDistance = distance;
            page = imageView.tag;
        }
    }
    self.pageControl.currentPage = page;
}

//開始拖拽的時候停止計時器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    [self stopTimer];
}

//結束拖拽的時候開始定時器
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    [self startTimer];
}

//結束拖拽的時候更新image內容
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self updateContent];
}

//scroll滾動動畫結束的時候更新image內容
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    [self updateContent];
}

#pragma mark - 定時器
//開始計時器
- (void)startTimer {
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.timer = timer;
}

//停止計時器
- (void)stopTimer {
    //結束計時
    [self.timer invalidate];
    //計時器被系統強引用,必須手動釋放
    self.timer = nil;
}

//通過改變contentOffset * 2換到下一張圖片
- (void)nextImage {
    CGFloat width = self.bounds.size.width;
    [self.scrollView setContentOffset:CGPointMake(2 * width, 0) animated:YES];
}

- (void)imageViewClick:(UITapGestureRecognizer *)tap {
    //    NSLog(@"%ld",btn.tag);
    UIView *imageView = tap.view;
    if ([self.delegate respondsToSelector:@selector(customerView:indexOfClickedImage:)])
    {
        [self.delegate customerView:self indexOfClickedImage:imageView.tag];
    }
    
}

@end

ViewController中調用代碼

#import "ViewController.h"
#import "CustomerView.h"

//遵守協議
@interface ViewController ()<CustomerViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //創建視圖
    CustomerView *customerView = [[CustomerView alloc] initWithFrame:CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, 300)];
    //設置代理
    customerView.delegate = self;
    //圖片數組賦值
    customerView.images = @[
                        [UIImage imageNamed:@"image_0.jpg"],
                        [UIImage imageNamed:@"image_1.jpg"],
                        [UIImage imageNamed:@"image_2.jpg"],
                        [UIImage imageNamed:@"image_3.jpg"]
                        ];
    
    customerView.currentPageColor = [UIColor whiteColor];
    customerView.pageColor = [UIColor blueColor];
    [self.view addSubview:customerView];
}

#pragma mark--CustomerViewDelegate  實現代理方法
- (void)customerView:(CustomerView *)view indexOfClickedImage:(NSInteger)index{
    NSLog(@"點擊了第%ld張圖片",index);
}

@end

全部代碼都已經貼出來了,就不再上傳demo了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章