轮播器(二)--采用两个ImageView和UIScrollView实现图片无限轮播

此篇文章介绍采用两个ImageView来实现无限轮播的方法,用于优化前篇的图片轮播

#import <UIKit/UIKit.h>

@protocol CarouselDelegate <NSObject>

//点击事件
-(void)clickedAtIndex:(NSInteger)index;

@end

@interface CarouselView2 : UIView

//代理
@property(assign,nonatomic) id<CarouselDelegate> delegate;

//数据源
@property (strong,nonatomic) NSMutableArray *dataSources;

//开启自动滚动
-(void)startAutoScroll;

@end
#import "CarouselView2.h"
#import "UIImageView+WebCache.h"
#import "CarouselModel.h"

@interface CarouselView2()<UIScrollViewDelegate>
//容器
@property (strong, nonatomic) UIScrollView *scrollView;
//分页控制器
@property (strong, nonatomic) UIPageControl *pageControl;
//定时器
@property (nonatomic , strong) NSTimer *timer;
//当前显示的imageView
@property (nonatomic, strong) UIImageView *currImageView;
//待显示的imageView
@property (nonatomic, strong) UIImageView *backImageView;
//当前显示图片的索引
@property (nonatomic, assign) NSInteger currIndex;
//待显示图片的索引
@property (nonatomic, assign) NSInteger nextIndex;
//是否自动滚动,默认为不自动滚动
@property (assign,nonatomic) BOOL autoScroll;

@end

@implementation CarouselView2

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initSubView];
    }
    return self;
}

- (void)initSubView {
    [self addSubview:self.scrollView];
    [self addSubview:self.pageControl];
}

- (CGFloat)height {
    return self.scrollView.frame.size.height;
}

- (CGFloat)width {
    return self.scrollView.frame.size.width;
}

#pragma mark 数据源的set方法
-(void)setDataSources:(NSMutableArray *)dataSources
{
    if (!dataSources.count) return;
    
    _dataSources = dataSources;
    
    //设置当前的imageview
    CarouselModel *model = [self.dataSources objectAtIndex:_currIndex];
    [self.currImageView sd_setImageWithURL:[[NSURL alloc] initWithString:model.imageUrl] placeholderImage:[UIImage imageNamed:@"1"]];
    //设置下一张图片
    model = [self.dataSources objectAtIndex:_nextIndex];
    [self.backImageView sd_setImageWithURL:[[NSURL alloc] initWithString:model.imageUrl] placeholderImage:[UIImage imageNamed:@"1"]];
    
    self.pageControl.numberOfPages = _dataSources.count;
    [self layoutSubviews];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    //有导航控制器时,会默认在scrollview上方添加64的内边距,这里强制设置为0
    _scrollView.contentInset = UIEdgeInsetsZero;
    
    _scrollView.frame = self.bounds;
    _pageControl.frame = CGRectMake(20, self.height - 30, self.width - 40, 30);
    [self setScrollViewContentSize];
}

#pragma mark 设置scrollView的contentSize
- (void)setScrollViewContentSize {
    if (_dataSources.count > 1) {
        self.scrollView.contentSize = CGSizeMake(self.width * 5, 0);
        self.scrollView.contentOffset = CGPointMake(self.width * 2, 0);
        self.currImageView.frame = CGRectMake(self.width * 2, 0, self.width, self.height);
        if(self.autoScroll)
        {
            [self startTimer];
        }
    } else {
        //只要一张图片时,scrollview不可滚动,且关闭定时器
        self.scrollView.contentSize = CGSizeZero;
        self.scrollView.contentOffset = CGPointZero;
        self.currImageView.frame = CGRectMake(0, 0, self.width, self.height);
        [self stopTimer];
    }
}

#pragma mark- --------定时器相关--------
-(void)startAutoScroll
{
    self.autoScroll = YES;
    [self startTimer];
}

- (void)startTimer {
    //如果只有一张图片,则直接返回,不开启定时器
    if (_dataSources.count <= 1) return;
    //如果定时器已开启,先停止再重新开启
    if (self.timer) [self stopTimer];
    self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)stopTimer {
    [self.timer invalidate];
    self.timer = nil;
    self.autoScroll = NO;
}

- (void)nextPage {
    [self.scrollView setContentOffset:CGPointMake(self.width * 3, 0) animated:YES];
}

#pragma mark 图片点击代理事件
- (void)imageClick {
    if ([_delegate respondsToSelector:@selector(clickedAtIndex:)]){
        [_delegate clickedAtIndex:self.currIndex];
    }
}

- (void)changeCurrentPageWithOffset:(CGFloat)offsetX {
    if (offsetX < self.width * 1.5) {
        NSInteger index = self.currIndex - 1;
        if (index < 0) index = self.dataSources.count - 1;
        _pageControl.currentPage = index;
    } else if (offsetX > self.width * 2.5){
        _pageControl.currentPage = (self.currIndex + 1) % self.dataSources.count;
    } else {
        _pageControl.currentPage = self.currIndex;
    }
}

#pragma mark- UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    if (CGSizeEqualToSize(CGSizeZero, scrollView.contentSize)) return;
    CGFloat offsetX = scrollView.contentOffset.x;
    //滚动过程中改变pageControl的当前页码
    [self changeCurrentPageWithOffset:offsetX];
    //向右滚动
    if (offsetX < self.width * 2) {
        self.backImageView.frame = CGRectMake(self.width, 0, self.width, self.height);
        
        self.nextIndex = self.currIndex - 1;
        if (self.nextIndex < 0) self.nextIndex = self.dataSources.count - 1;
        CarouselModel *model = [self.dataSources objectAtIndex:self.nextIndex];
        [self.backImageView sd_setImageWithURL:[[NSURL alloc] initWithString:model.imageUrl] placeholderImage:[UIImage imageNamed:@"1"]];
        if (offsetX <= self.width) [self changeToNext];
        
        //向左滚动
    } else if (offsetX > self.width * 2){
        self.backImageView.frame = CGRectMake(CGRectGetMaxX(_currImageView.frame), 0, self.width, self.height);
        
        self.nextIndex = (self.currIndex + 1) % self.dataSources.count;
        CarouselModel *model = [self.dataSources objectAtIndex:self.nextIndex];
        [self.backImageView sd_setImageWithURL:[[NSURL alloc] initWithString:model.imageUrl] placeholderImage:[UIImage imageNamed:@"1"]];
        if (offsetX >= self.width * 3) [self changeToNext];
    }
}

- (void)changeToNext {
    //切换到下一张图片
    self.currImageView.image = self.backImageView.image;
    self.scrollView.contentOffset = CGPointMake(self.width * 2, 0);
    [self.scrollView layoutSubviews];
    self.currIndex = self.nextIndex;
    self.pageControl.currentPage = self.currIndex;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    if (self.autoScroll) {
        [self stopTimer];
    }
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    if(self.autoScroll)
    {
        [self startTimer];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    CGPoint currPointInSelf = [_scrollView convertPoint:_currImageView.frame.origin toView:self];
    if (currPointInSelf.x >= -self.width / 2 && currPointInSelf.x <= self.width / 2)
        [self.scrollView setContentOffset:CGPointMake(self.width * 2, 0) animated:YES];
    else [self changeToNext];
}

#pragma mark- 懒加载
- (UIScrollView *)scrollView {
    if (!_scrollView) {
        _scrollView = [[UIScrollView alloc] init];
        _scrollView.scrollsToTop = NO;
        _scrollView.pagingEnabled = YES;
        _scrollView.bounces = NO;
        _scrollView.showsHorizontalScrollIndicator = NO;
        _scrollView.showsVerticalScrollIndicator = NO;
        _scrollView.delegate = self;
        //添加手势监听图片的点击
        [_scrollView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageClick)]];
        _currImageView = [[UIImageView alloc] init];
        _currImageView.clipsToBounds = YES;
        [_scrollView addSubview:_currImageView];
        _backImageView = [[UIImageView alloc] init];
        _backImageView.clipsToBounds = YES;
        [_scrollView addSubview:_backImageView];
    }
    return _scrollView;
}

- (UIPageControl *)pageControl {
    if (!_pageControl) {
        _pageControl = [[UIPageControl alloc] init];
        _pageControl.userInteractionEnabled = NO;
        _pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
        _pageControl.pageIndicatorTintColor = [UIColor grayColor];
    }
    return _pageControl;
}

@end

VC中使用

self.automaticallyAdjustsScrollViewInsets = NO;
    
    NSMutableArray *dataList = [[NSMutableArray alloc]init];
    NSMutableArray *dataArr = [[NSMutableArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"carouselArr.plist" ofType:nil]];
    for (NSDictionary *dic in dataArr) {
        CarouselModel *model = [[CarouselModel alloc]init];
        model.imageUrl = [dic objectForKey:@"imageUrl"];
        model.contentUrl = [dic objectForKey:@"contentUrl"];
        model.labelText = [dic objectForKey:@"textLable"];
        [dataList addObject:model];
    }
    
    CarouselView2 *view1 = [[CarouselView2 alloc]initWithFrame:CGRectMake(20, 100, self.view.frame.size.width - 40, (self.view.frame.size.width - 40) * 0.5)];
    view1.delegate = self;
    view1.dataSources = dataList;
    [view1 startAutoScroll];
    [self.view addSubview:view1];



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值