iOS无限轮播封装

无限轮播封装(代码主要参考这里)
http://blog.cocoachina.com/article/34641

三张Imageview实现无限图片轮播
http://my.oschina.net/iOSliuhui/blog/497070

iOS无限轮播图片的实现-仅仅用了三个UIImageView实现多图的轮播效果
http://blog.csdn.net/techfu/article/details/49888999

iOS开发--轮播图(无限循环)新玩法--视差轮播--无限循环的新思路(两个UIImageView足矣)
http://blog.csdn.net/wswei99/article/details/50827632

iOS开发之只用一个方法实现图片的轮播
http://www.imooc.com/article/12806

使用三个UIImageView实现多图的轮播效果

原理很简单,就是放上3个UIImageView, 默认显示的是中间的UIImageView,
当用户滑到下一张图片的临界点时候,偷偷的切换回中间的UIImageView展示,但是UIImage却全部换掉了;也就是说用户永远看到的是中间的UIImageView,只是内容不同而已。

1、BannerView.h文件

#import <UIKit/UIKit.h>

/**
 *  原理很简单,就是放上3个UIImageView, 默认显示的是中间的UIImageView,
 *  当用户滑到下一张图片的临界点时候,偷偷的切换回中间的UIImageView展示,但是UIImage却全部换掉了;
 *  也就是说用户永远看到的是中间的UIImageView,只是内容不同而已。
 *
 */

@class BannerView;
@protocol BannerViewDelegate <NSObject>

- (void) carouselTouch:(BannerView*)carousel atIndex:(NSUInteger)index;

@end

@interface BannerView : UIView

@property (nonatomic, copy) void(^bannerTouchBlock)(NSUInteger index);

@property (nonatomic, weak) id<BannerViewDelegate> delegate;

- (instancetype)initWithFrame:(CGRect)frame;

/**
 *  轮播图url数组
 *
 */
- (void)setupWithArray:(NSArray *)array;

/**
 *  本地图片数组;
 */
- (void)setupWithLocalArray:(NSArray *)array;

/**
 *  类初始化方法;
 *
 */
+ (instancetype)initWithFrame:(CGRect)frame
                    withArray:(NSArray*)array
                     hasTimer:(BOOL)hastimer
                     interval:(NSUInteger)inter;

+ (instancetype)initWithFrame:(CGRect)frame
                     hasTimer:(BOOL)hastimer
                     interval:(NSUInteger)inter
                  placeHolder:(UIImage*)image;

@end

2、BannerView.m文件

#import "BannerView.h"

#import <SDWebImage/UIImageView+WebCache.h>

@interface BannerView () <UIScrollViewDelegate>

@property BOOL hasTimer;
@property (nonatomic, assign) NSUInteger interval;

@property (nonatomic, strong) UIImage *placeHolder;

@property (nonatomic, strong) NSArray * imageArray;

@property (nonatomic, strong) UIScrollView *wheelScrollView;        // scrollView
@property (nonatomic, strong) UIPageControl *wheelPageControl;      // pageControl

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) NSUInteger currentImageIndex;

@property (nonatomic, strong) UIImageView *image1;
@property (nonatomic, strong) UIImageView *image2;
@property (nonatomic, strong) UIImageView *image3;

@property (nonatomic, assign) NSUInteger imageNum;

@property (nonatomic, strong) UIImageView *mask;
@property (nonatomic, assign) BOOL isLocal;

@end

@implementation BannerView

#pragma mark - init
+ (instancetype)initWithFrame:(CGRect)frame
                    withArray:(NSArray*)array
                     hasTimer:(BOOL)hastimer
                     interval:(NSUInteger)inter
{
    BannerView * carousel = [[BannerView alloc] initWithFrame:frame];
    carousel.hasTimer = hastimer;
    carousel.interval = inter;
    
    [carousel setupWithArray:array];
    return carousel;
}

+ (instancetype)initWithFrame:(CGRect)frame
                     hasTimer:(BOOL)hastimer
                     interval:(NSUInteger)inter
                  placeHolder:(UIImage*)image
{
    BannerView * carousel = [[BannerView alloc] initWithFrame:frame];
    carousel.placeHolder = image;
    carousel.hasTimer = hastimer;
    carousel.interval = inter;
    carousel.mask.image = image;
    
    
    return carousel;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.mask = [[UIImageView alloc] initWithFrame:frame];
        [self addSubview:self.wheelScrollView];
        [self addSubview:self.wheelPageControl];
        [self addSubview:self.mask];
        self.wheelScrollView.scrollEnabled = NO;
    }
    return self;
}


- (void)setupWithArray:(NSArray *)array
{
    self.wheelScrollView.scrollEnabled = YES;
    self.mask.hidden = YES;
    self.imageArray = array;
    self.imageNum = self.imageArray.count;
    self.currentImageIndex = 0;
    
    if (self.imageNum == 1) {
        self.wheelPageControl.hidden = YES;
        self.wheelScrollView.scrollEnabled = NO;
    }
    
    [self setup];
}

- (void)setupWithLocalArray:(NSArray *)array
{
    self.isLocal = YES;
    self.wheelScrollView.scrollEnabled = YES;
    self.mask.hidden = YES;
    self.imageArray = array;
    self.imageNum = self.imageArray.count;
    self.currentImageIndex = 0;
    
    if (self.imageNum == 1) {
        self.wheelPageControl.hidden = YES;
        self.wheelScrollView.scrollEnabled = NO;
    }
    
    [self setup];
}

/**
 *  初始化,启动定时器;轮播图片
 */
- (void)setup
{
    // 设置PageControl中心点
    self.wheelPageControl.pageIndicatorTintColor = [UIColor whiteColor];
    self.wheelPageControl.currentPageIndicatorTintColor = [UIColor blackColor];
    CGPoint p = CGPointMake(self.frame.size.width * 0.5, 0.92 * self.frame.size.height);
    self.wheelPageControl.center = p;
    
    if (self.hasTimer) {
        [self setupTimer];
    }
    [self updateImage];
}

/**
 *  图片更新
 */
- (void)updateImage
{
    self.imageNum = (int)self.imageArray.count;
    self.wheelPageControl.numberOfPages = self.imageNum;
    
    [self updateScrollImage];
}



- (void)updateScrollImage
{
    int left;
    int right;
    
    // 计算页数
    int page = self.wheelScrollView.contentOffset.x / self.wheelScrollView.frame.size.width;
    if (page == 0)
    {
        // 计算当前图片索引
        self.currentImageIndex = (self.currentImageIndex + self.imageNum - 1) % self.imageNum;   // %限定当前索引不越界;
    }
    else if(page == 2)
    {
        // 计算当前图片索引
        self.currentImageIndex = (self.currentImageIndex + 1) % self.imageNum;
    }
    
    // 当前图片左右索引
    left = (int)(self.currentImageIndex + self.imageNum - 1) % self.imageNum;
    right = (int)(self.currentImageIndex + 1) % self.imageNum;
    
    // 更换UIImage
    if (self.isLocal)
    {
        self.image1.image = [UIImage imageNamed:self.imageArray[left]];
        self.image2.image = [UIImage imageNamed:self.imageArray[self.self.currentImageIndex]];
        self.image3.image = [UIImage imageNamed:self.imageArray[right]];
    }
    else
    {
        [self.image1 sd_setImageWithURL:[NSURL URLWithString:self.imageArray[left]]  placeholderImage:self.placeHolder];
        [self.image2 sd_setImageWithURL:[NSURL URLWithString:self.imageArray[self.currentImageIndex]] placeholderImage:self.placeHolder];
        [self.image3 sd_setImageWithURL:[NSURL URLWithString:self.imageArray[right]] placeholderImage:self.placeHolder];
    }
    
    self.wheelPageControl.currentPage = self.currentImageIndex;
    [self.wheelScrollView setContentOffset:CGPointMake(self.wheelScrollView.frame.size.width, 0) animated:NO];
}

#pragma mark - NSTimer
- (void)setupTimer
{
    if (self.interval == 0)
    {
        self.interval = 3;
    }
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval target:self selector:@selector(updateWheel) userInfo:nil repeats:YES];
    
    // 避免tableview滚动时,定时器停止;
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)updateWheel
{
    CGPoint offset = self.wheelScrollView.contentOffset;
    offset.x += self.wheelScrollView.frame.size.width;
    [self.wheelScrollView setContentOffset:offset animated:YES];
}



- (void)destroy
{
    [self.timer invalidate];
}

#pragma mark - UIScrollView
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    [self updateScrollImage];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self updateScrollImage];
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.timer invalidate];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    [self setupTimer];
}


- (void)touchAction
{
    if ([self.delegate respondsToSelector:@selector(carouselTouch:atIndex:)]) {
        [self.delegate carouselTouch:self atIndex:self.currentImageIndex];
    }
    
    // 使用block的回调
    if (self.bannerTouchBlock)
    {
        self.bannerTouchBlock(self.currentImageIndex);
    }
}

#pragma mark - Getter

- (UIScrollView *)wheelScrollView
{
    if (!_wheelScrollView)
    {
        _wheelScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
        _wheelScrollView.backgroundColor = [UIColor clearColor];
        _wheelScrollView.pagingEnabled = YES;
        _wheelScrollView.delegate = self;
        _wheelScrollView.showsHorizontalScrollIndicator = NO;
        _wheelScrollView.showsVerticalScrollIndicator = NO;
        
        // 添加点击事件
        UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchAction)];
        [_wheelScrollView addGestureRecognizer:tap];
        
        // 使用3个UIImageView,
        _image1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
        _image2 = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width, 0, self.frame.size.width, self.frame.size.height)];
        _image3 = [[UIImageView alloc] initWithFrame:CGRectMake(2*self.frame.size.width, 0, self.frame.size.width, self.frame.size.height)];
        _image2.image = self.placeHolder;
        
        for (UIImageView * img in @[_image1,_image2,_image3]) {
            [_wheelScrollView addSubview:img];
        }
        
        [_wheelScrollView setContentOffset:CGPointMake(self.frame.size.width, 0) animated:NO];
        _wheelScrollView.scrollEnabled = YES;
        _wheelScrollView.contentSize = CGSizeMake(3*self.frame.size.width, self.frame.size.height);
    }
    return _wheelScrollView;
}

- (UIPageControl *)wheelPageControl
{
    if (!_wheelPageControl)
    {
        _wheelPageControl = [[UIPageControl alloc] init];
        [_wheelPageControl setBackgroundColor:[UIColor clearColor]];
        _wheelPageControl.currentPage = 0;
        _wheelPageControl.numberOfPages = self.imageNum;
    }
    
    return _wheelPageControl;
}


@end

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容