对于图像轮播框架的实现,网上有很多种方法,可以使用UIScrollView,也可以使用UICollectionView。
今天就撸一波代码,打算使用3个UIImageView实现,这样比较节省内存(个人偏向于这个方案),当然由于UICollectionView的Cell有复用机制,也比较好。
思路:1)在UIScrollView上面添加3个UIImageView,分别为leftImageView,centerImageView,RightImageView
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
demo传送门:https://git.oschina.net/heren/CHRScrollView.git