我們會(huì)經(jīng)常用到循環(huán)滾動(dòng)圖片,包括定時(shí)滾動(dòng)箕戳,點(diǎn)擊觸發(fā)事件。
以前所知道的循環(huán)滾動(dòng)圖片的方法是這樣的友驮。比如:一共5張圖片漂羊,位置為1,2,3,4,5
。
- 創(chuàng)建7個(gè)
imageView
卸留。 - 將最后一張圖片放到第一張圖片前面,將第一張圖片放到最后一張后面椭豫,位置為
5,1,2,3,4,5,1
耻瑟。 - 最后一張圖片滾動(dòng)到第一張圖片時(shí),先從第二個(gè)圖片5滾動(dòng)到第二個(gè)圖片1赏酥,滾動(dòng)完之后把位置設(shè)置為第一個(gè)圖片1喳整。從后向前滾動(dòng)同樣的原理。
- 在
scrollViewDidScroll
的代理方法里面判斷scrollView.contentOffset.x>320*6-1
裸扶,將scrollView
的偏移量設(shè)置為320
的位置框都,動(dòng)畫(huà)設(shè)置為NO
。 - 這樣做的原因是從第二個(gè)圖片5滾動(dòng)到第二個(gè)圖片1之后偏移量是
320*6
呵晨,這個(gè)值是大于320*6-1
的魏保,進(jìn)入到if
語(yǔ)句,將scrollView
設(shè)置320
的位置摸屠,則就是第一個(gè)圖片1的位置谓罗,這樣就造成一個(gè)視覺(jué)差,是從最后一張圖片滾動(dòng)到第一張圖片的季二。
以前是那么用的檩咱,但是后來(lái)覺(jué)得這樣比較占資源,也比較麻煩胯舷,現(xiàn)在是這樣的刻蚯,不管多少?gòu)垐D片只創(chuàng)建3個(gè)imageView
。
- 從
viewController
中取到圖片數(shù)據(jù)源桑嘶,創(chuàng)建當(dāng)前需要展示的圖片數(shù)組長(zhǎng)度是3炊汹,當(dāng)前展示的圖片位置默認(rèn)是0。 - 當(dāng)前數(shù)組根據(jù)當(dāng)前位置取出3張圖片不翩,當(dāng)前展示的圖片的前一張和后一張兵扬。如果當(dāng)前需要展示的圖片是第一張麻裳,則當(dāng)前數(shù)組中的3張圖片為圖片5、圖片1器钟、圖片2津坑。如果當(dāng)前需要展示的圖片是最后一張圖片,則當(dāng)前數(shù)組中的3張圖片為圖片4傲霸、圖片5疆瑰、圖片1。
- 這樣展示的圖片是第2張圖片昙啄,偏移量為
320
穆役,滑動(dòng)到下一張圖片的時(shí)候,設(shè)置當(dāng)前位置為1梳凛,設(shè)置當(dāng)前數(shù)組圖片為圖片1耿币、圖片2、圖片3韧拒,刷新UI淹接,并且把scrollView
的偏移量設(shè)置為320
,即展示的圖片永遠(yuǎn)在中間叛溢。 - 點(diǎn)擊圖片觸發(fā)的事件通過(guò)代理傳出當(dāng)前的圖片位置塑悼。
CycleScrollView.h中的代碼
#import <UIKit/UIKit.h>
@protocol CycleScrollViewDelegate;
@interface CycleScrollView : UIView<UIScrollViewDelegate>
數(shù)據(jù)源
@property (nonatomic, strong) NSArray *imageArray;
滾動(dòng)視圖。本來(lái)是不需要這個(gè)屬性的楷掉,但是有個(gè)問(wèn)題:如果圖片正好滾動(dòng)了一半app進(jìn)入到后臺(tái)厢蒜,再次打開(kāi)的時(shí)候是滾動(dòng)到一半狀態(tài),滾動(dòng)到下一張圖片的時(shí)候就好了烹植,所以把這個(gè)問(wèn)題在viewController
里面處理斑鸦。
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, weak) id<CycleScrollViewDelegate> delegate;
@end
代理方法
@protocol CycleScrollViewDelegate <NSObject>
- (void)cycleScrollView:(CycleScrollView *)cycleScrollView didSelectImageView:(NSInteger)index;
@end
CycleScrollView.m中的代碼
#import "CycleScrollView.h"
#import "ImageModel.h" //圖片model
#import "UIImageView+WebCache.h" //SDWebImage設(shè)置網(wǎng)絡(luò)圖片
#define c_width (self.bounds.size.width+10) //兩張圖片之前有10點(diǎn)的間隔
#define c_height (self.bounds.size.height)
@implementation CycleScrollView
{
UIPageControl *_pageControl; //分頁(yè)控件
NSMutableArray *_curImageArray; //當(dāng)前顯示的圖片數(shù)組
NSInteger _curPage; //當(dāng)前顯示的圖片位置
NSTimer *_timer; //定時(shí)器
}
重寫(xiě)init
方法
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//滾動(dòng)視圖
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, c_width, c_height)];
self.scrollView.contentSize = CGSizeMake(c_width*3, 0);
self.scrollView.contentOffset = CGPointMake(c_width, 0);
self.scrollView.pagingEnabled = YES;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.delegate = self;
[self addSubview:self.scrollView];
//分頁(yè)控件
_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, c_height-30, self.bounds.size.width, 30)];
_pageControl.userInteractionEnabled = NO;
_pageControl.hidesForSinglePage = YES;
_pageControl.currentPageIndicatorTintColor = [UIColor redColor];
_pageControl.pageIndicatorTintColor = [UIColor grayColor];
[self addSubview:_pageControl];
//初始化數(shù)據(jù),當(dāng)前圖片默認(rèn)位置是0
_curImageArray = [[NSMutableArray alloc] initWithCapacity:0];
_curPage = 0;
}
return self;
}
scrollView
的代理方法
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//如果scrollView當(dāng)前偏移位置x大于等于兩倍scrollView寬度
if (scrollView.contentOffset.x >= c_width*2) {
//當(dāng)前圖片位置+1
_curPage++;
//如果當(dāng)前圖片位置超過(guò)數(shù)組邊界刊橘,則設(shè)置為0
if (_curPage == [self.imageArray count]) {
_curPage = 0;
}
//刷新圖片
[self reloadData];
//設(shè)置scrollView偏移位置
[scrollView setContentOffset:CGPointMake(c_width, 0)];
}
//如果scrollView當(dāng)前偏移位置x小于等于0
else if (scrollView.contentOffset.x <= 0) {
//當(dāng)前圖片位置-1
_curPage--;
//如果當(dāng)前圖片位置小于數(shù)組邊界鄙才,則設(shè)置為數(shù)組最后一張圖片下標(biāo)
if (_curPage == -1) {
_curPage = [self.imageArray count]-1;
}
//刷新圖片
[self reloadData];
//設(shè)置scrollView偏移位置
[scrollView setContentOffset:CGPointMake(c_width, 0)];
}
}
//停止?jié)L動(dòng)的時(shí)候回調(diào)
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
//設(shè)置scrollView偏移位置
[scrollView setContentOffset:CGPointMake(c_width, 0) animated:YES];
}
重寫(xiě)圖片數(shù)組的set
方法
- (void)setImageArray:(NSMutableArray *)imageArray
{
_imageArray = imageArray;
//設(shè)置分頁(yè)控件的總頁(yè)數(shù)
_pageControl.numberOfPages = imageArray.count;
//刷新圖片
[self reloadData];
//開(kāi)啟定時(shí)器
if (_timer) {
[_timer invalidate];
_timer = nil;
}
//判斷圖片長(zhǎng)度是否大于1,如果一張圖片不開(kāi)啟定時(shí)器
if ([imageArray count] > 1) {
_timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerScrollImage) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runMode:UITrackingRunLoopMode beforeDate:[NSDate date]];
}
}
刷新圖片的方法
- (void)reloadData
{
//設(shè)置頁(yè)數(shù)
_pageControl.currentPage = _curPage;
//根據(jù)當(dāng)前頁(yè)取出圖片
[self getDisplayImagesWithCurpage:_curPage];
//從scrollView上移除所有的subview
NSArray *subViews = [self.scrollView subviews];
if ([subViews count] > 0) {
[subViews makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
//創(chuàng)建imageView
for (int i = 0; i < 3; i++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(c_width*i, 0, self.bounds.size.width, c_height)];
imageView.userInteractionEnabled = YES;
[self.scrollView addSubview:imageView];
//設(shè)置網(wǎng)絡(luò)圖片
ImageModel *model = _curImageArray[i];
NSURL *url = [NSURL URLWithString:model.image_url];
[imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"placeholder_320x120.png"]];
//tap手勢(shì)
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapImage:)];
[imageView addGestureRecognizer:tap];
}
}
獲取圖片
- (void)getDisplayImagesWithCurpage:(NSInteger)page
{
//取出開(kāi)頭和末尾圖片在圖片數(shù)組里的下標(biāo)
NSInteger front = page - 1;
NSInteger last = page + 1;
//如果當(dāng)前圖片下標(biāo)是0促绵,則開(kāi)頭圖片設(shè)置為圖片數(shù)組的最后一個(gè)元素
if (page == 0) {
front = [self.imageArray count]-1;
}
//如果當(dāng)前圖片下標(biāo)是圖片數(shù)組最后一個(gè)元素攒庵,則設(shè)置末尾圖片為圖片數(shù)組的第一個(gè)元素
if (page == [self.imageArray count]-1) {
last = 0;
}
//如果當(dāng)前圖片數(shù)組不為空,則移除所有元素
if ([_curImageArray count] > 0) {
[_curImageArray removeAllObjects];
}
//當(dāng)前圖片數(shù)組添加圖片
[_curImageArray addObject:self.imageArray[front]];
[_curImageArray addObject:self.imageArray[page]];
[_curImageArray addObject:self.imageArray[last]];
}
定時(shí)器的方法
- (void)timerScrollImage
{
//刷新圖片
[self reloadData];
//設(shè)置scrollView偏移位置
[self.scrollView setContentOffset:CGPointMake(c_width*2, 0) animated:YES];
}
tap
圖片的方法
- (void)tapImage:(UITapGestureRecognizer *)tap
{
//設(shè)置代理
if ([_delegate respondsToSelector:@selector(cycleScrollView:didSelectImageView:)]) {
[_delegate cycleScrollView:self didSelectImageView:_curPage];
}
}
dealloc
方法
- (void)dealloc
{
//代理指向nil败晴,關(guān)閉定時(shí)器
self.scrollView.delegate = nil;
[_timer invalidate];
}
@end
viewController里面的代碼
#import "CycleScrollView.h"
@interface RootViewController:BaseViewController<CycleScrollViewDelegate>
@property (nonatomic, strong) CycleScrollView *imageScrollView;
self.imageScrollView = [[CycleScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 120)];
self.imageScrollView.delegate = self;
[headerView addSubview:self.imageScrollView];
獲取到的網(wǎng)絡(luò)數(shù)據(jù)方法里浓冒,設(shè)置循環(huán)滾動(dòng)圖片的圖片數(shù)組
if ( [[resultDict objectForKey:@"big_image_list"] count] > 0) {
self.imageArray = [resultDict objectForKey:@"big_image_list"];
self.imageScrollView.imageArray = self.imageArray;
}
代理方法回調(diào)
#pragma mark - CycleScrollViewDelegate
- (void)cycleScrollView:(CycleScrollView *)cycleScrollView didSelectImageView:(NSInteger)index
{
NSLog(@"點(diǎn)擊了第%ld張圖片",(long)index+1);
ImageModel *model = self.imageArray[index];
}
處理圖片正好滾動(dòng)了一半app進(jìn)入到后臺(tái),再次打開(kāi)的時(shí)候是滾動(dòng)到一半狀態(tài)的問(wèn)題尖坤。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//設(shè)置圖片循環(huán)滾動(dòng)稳懒,如果偏移位置大于330,則設(shè)置為330
if (self.imageScrollView.scrollView.contentOffset.x > 330) {
self.imageScrollView.scrollView.contentOffset = CGPointMake(330*2, 0);
}
}