iOS 循环轮播框架,使用3个UIImageView实现

对于图像轮播框架的实现,网上有很多种方法,可以使用UIScrollView,也可以使用UICollectionView。

今天就撸一波代码,打算使用3个UIImageView实现,这样比较节省内存(个人偏向于这个方案),当然由于UICollectionView的Cell有复用机制,也比较好。

思路:1)在UIScrollView上面添加3个UIImageView,分别为leftImageView,centerImageView,RightImageView

   iOS 循环轮播框架,使用3个UIImageView实现_第1张图片

  2)UIScrollView初始化时,contentOffset停留在中间的UIImageView

                  3)使用一个定时器,定时器触发是,把contentOffset从中间通过动画滑动到第三个UIImageView的位置

  4)滑动完成时候,要进行最关键的复位操作,就是迅速把contentOffset切换回第二个UIImageView的位置,但是切换前,先centerImageView.image = rightjImageView.image,注意,这里不适用动画,所以用户看不出来切换了

  5)下次定时器触发时,又把contentOffset从第二个位置通过动画滑动到第三个位置

         6)事实上2个UIImageView就可以实现,但是左边一直有一个提供用户手动向左滑动


不费话了,贴代码:

头文件:

//
//  CHRDanTangHeaderScrollView.h
//  test
//
//  Created by Chen Heren on 16/10/12.
//  Copyright (c) 2016年 Chen Heren. All rights reserved.
//

#import 

@class CHRDanTangHeaderScrollView;

@protocol CHRDanTangHeaderScrollViewDelegate 

-(void)DanTangHeaderScrollView:(CHRDanTangHeaderScrollView *)scrollView selectedAt:(NSInteger)index;

@end

@interface CHRDanTangHeaderScrollView : UIView

@property (strong, nonatomic) NSArray *imageUrls;

@property (nonatomic) CGFloat intervalTime;

@property (weak, nonatomic) id delegate;

-(instancetype)initWithFrame:(CGRect)frame ImageUrls:(NSArray *)imageUrls IntervalTime:(CGFloat)intervalTime;

@end

源文件:

//
//  CHRDanTangHeaderScrollView.m
//  采用3个UIImageView实现循环显示
//  思路:暗渡陈仓
//  定时器Fire时,正常进行滑动,待滑动完成,重新把视图contentoffset恢复到中间uiimageview的状态
//  Created by Chen Heren on 16/10/12.
//  Copyright (c) 2016年 Chen Heren. All rights reserved.
//

#import "CHRDanTangHeaderScrollView.h"
#import "UIImageView+WebCache.h"


@interface CHRDanTangHeaderScrollView ()

///滑动视图
@property (strong, nonatomic) UIScrollView *scrollView;
///指示器
@property (strong, nonatomic) UIPageControl *pageControl;
///左UIImageView
@property (strong, nonatomic) UIImageView *leftImageView;
///中间UIImageView
@property (strong, nonatomic) UIImageView *centerImageView;
///右UIImageView
@property (strong, nonatomic) UIImageView *rightImageView;

@property (nonatomic) NSInteger currentPage;

@property (strong, nonatomic) NSTimer *timer;

@end

@implementation CHRDanTangHeaderScrollView


-(instancetype)initWithFrame:(CGRect)frame ImageUrls:(NSArray *)imageUrls IntervalTime:(CGFloat)intervalTime{
    self = [self initWithFrame:frame];
    if (self) {
        self.imageUrls = [NSArray arrayWithArray:imageUrls];
        self.intervalTime = intervalTime;
        self.currentPage = 0;
        [self setupUI];
    }
    return self;
}

-(void)setupUI{
    
    [self addSubview:self.scrollView];
    [self addSubview:self.pageControl];
    [self setupImageView];
    [self setupTimer];
}

-(UIScrollView *)scrollView{
    if (_scrollView == nil) {
        _scrollView = [[UIScrollView alloc]initWithFrame:self.bounds];
        _scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.scrollView.frame) * 3, CGRectGetHeight(self.scrollView.frame));
        _scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
        _scrollView.delegate = self;
        _scrollView.pagingEnabled = YES;
        _scrollView.showsHorizontalScrollIndicator = NO;
        _scrollView.decelerationRate = 1.0;
        _scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame), 0);
    }
    return _scrollView;
}

-(UIPageControl *)pageControl{
    if (_pageControl == nil) {
        _pageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(self.frame.size.width/2-50, self.frame.size.height-35, 100, 30)];
        _pageControl.numberOfPages = self.imageUrls.count;
        _pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
        _pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
    }
    return _pageControl;
}

-(void)setupImageView{
    
    self.leftImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *0, 0, self.frame.size.width, self.frame.size.height)];
    self.centerImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *1, 0, self.frame.size.width, self.frame.size.height)];
    self.rightImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *2, 0, self.frame.size.width, self.frame.size.height)];
    
    [self.leftImageView sd_setImageWithURL:[self getImageUrlBeforeIndex:self.currentPage]];
    [self.centerImageView sd_setImageWithURL:[self getImageUrlAtIndex:self.currentPage]];
    [self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]];
    
    self.leftImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.centerImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.rightImageView.contentMode = UIViewContentModeScaleAspectFit;
    
    ///用户看到的只有中间视图,所以为了简单起见,只需要添加中间视图的点击响应
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageViewTap)];
    self.centerImageView.userInteractionEnabled =  YES;
    [self.centerImageView addGestureRecognizer:tap];

    
    [self.scrollView addSubview:self.leftImageView];
    [self.scrollView addSubview:self.centerImageView];
    [self.scrollView addSubview:self.rightImageView];
    
}

-(void)setupTimer{
    self.timer = [NSTimer timerWithTimeInterval:self.intervalTime target:self selector:@selector(timerTick) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];
}


-(void)timerTick{
    self.currentPage++;
    if (self.currentPage == self.imageUrls.count) {
        self.currentPage = 0;
    }
    ///此处设置动画的时间一定要小于滑动的时间
    [UIView animateWithDuration:1 animations:^{
        ///动画发生的滑动
        self.centerImageView.userInteractionEnabled =NO;
        self.scrollView.contentOffset =CGPointMake(CGRectGetWidth(self.scrollView.frame) * 2, 0);
    } completion:^(BOOL finished) {
        ///滑动完成后,把当前现实的imageview重现移动回中间位置,此处不能使用动画,用户感觉不到
        ///移动前,先把中间imageview的image设置成当前现实的iamge
        self.centerImageView.userInteractionEnabled = YES;
        self.leftImageView.image = self.centerImageView.image;
        self.centerImageView.image = self.rightImageView.image;
        self.scrollView.contentOffset =CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0);
        [self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]];
        self.pageControl.currentPage = self.currentPage;
    }];
    

}

#pragma mark - 用户点击

-(void)imageViewTap{
    NSLog(@"tap at :%ld",self.currentPage);
    [self.delegate DanTangHeaderScrollView:self selectedAt:self.currentPage];
}

#pragma mark - 循环获取URL

-(NSURL *)getImageUrlBeforeIndex:(NSInteger)index{
    if (index == 0) {
        return [self.imageUrls lastObject];
    }else{
        return self.imageUrls[index-1];
    }
}

-(NSURL *)getImageUrlAfterIndex:(NSInteger)index{
    if (index == (self.imageUrls.count - 1)) {
        return [self.imageUrls firstObject];
    }else{
        return self.imageUrls[index+1];
    }
}

-(NSURL *)getImageUrlAtIndex:(NSInteger)index{
    if (index<0 || index >= self.imageUrls.count) {
        return nil;
    }else{
        return self.imageUrls[index];
    }
}

#pragma mark - scrollView滑动事件

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    ///有用户手动拖动,则停止定时器
    [self.timer invalidate];
}

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    ///用户滑动停止,重新启动定时器
    [self setupTimer];
}

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    NSInteger index = scrollView.contentOffset.x/scrollView.frame.size.width;
    if (index ==0) {
        //向左滑动
        self.currentPage--;
        if (self.currentPage <0 ) {
            self.currentPage = self.imageUrls.count;
        }
        self.rightImageView.image = self.centerImageView.image;
        self.centerImageView.image = self.leftImageView.image;
        scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0);
        [self.leftImageView sd_setImageWithURL:[self getImageUrlBeforeIndex:self.currentPage]];
         self.pageControl.currentPage = self.currentPage;
    }else if(index == 2){
        ///向右滑动
        self.currentPage++;
        if (self.currentPage ==self.imageUrls.count ) {
            self.currentPage = 0;
        }
        self.leftImageView.image = self.centerImageView.image;
        self.centerImageView.image = self.rightImageView.image;
        scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0);
        [self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]];
         self.pageControl.currentPage = self.currentPage;
    }
    ///没有滑动一页
}




@end

使用:
#import "ViewController.h"
#import  "CHRDanTangHeaderScrollView.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSURL *url = [[NSBundle mainBundle]URLForResource:@"1" withExtension:@".png"];
    NSURL *ur2 = [[NSBundle mainBundle]URLForResource:@"2" withExtension:@".png"];
    NSURL *ur3 = [[NSBundle mainBundle]URLForResource:@"3" withExtension:@".png"];
    NSURL *ur4 = [[NSBundle mainBundle]URLForResource:@"4" withExtension:@".png"];
    CHRDanTangHeaderScrollView *scrollView = [[CHRDanTangHeaderScrollView alloc]initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 200) ImageUrls:@[url,ur2,ur3,ur4] IntervalTime:2];
    scrollView.delegate = self;
    [self.view addSubview:scrollView];
    
}


-(void)DanTangHeaderScrollView:(CHRDanTangHeaderScrollView *)scrollView selectedAt:(NSInteger)index{
    NSLog(@"%ld",index);
}

@end


iOS 循环轮播框架,使用3个UIImageView实现_第2张图片

iOS 循环轮播框架,使用3个UIImageView实现_第3张图片


demo传送门:https://git.oschina.net/heren/CHRScrollView.git

你可能感兴趣的:(IOS开发)