UIScrollView(循環(huán)滾動(dòng)圖片)

我們會(huì)經(jīng)常用到循環(huán)滾動(dòng)圖片,包括定時(shí)滾動(dòng)箕戳,點(diǎn)擊觸發(fā)事件。
以前所知道的循環(huán)滾動(dòng)圖片的方法是這樣的友驮。比如:一共5張圖片漂羊,位置為1,2,3,4,5

  1. 創(chuàng)建7個(gè)imageView卸留。
  2. 將最后一張圖片放到第一張圖片前面,將第一張圖片放到最后一張后面椭豫,位置為5,1,2,3,4,5,1耻瑟。
  3. 最后一張圖片滾動(dòng)到第一張圖片時(shí),先從第二個(gè)圖片5滾動(dòng)到第二個(gè)圖片1赏酥,滾動(dòng)完之后把位置設(shè)置為第一個(gè)圖片1喳整。從后向前滾動(dòng)同樣的原理。
  4. scrollViewDidScroll的代理方法里面判斷scrollView.contentOffset.x>320*6-1裸扶,將scrollView的偏移量設(shè)置為320的位置框都,動(dòng)畫(huà)設(shè)置為NO
  5. 這樣做的原因是從第二個(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

  1. viewController中取到圖片數(shù)據(jù)源桑嘶,創(chuàng)建當(dāng)前需要展示的圖片數(shù)組長(zhǎng)度是3炊汹,當(dāng)前展示的圖片位置默認(rèn)是0。
  2. 當(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。
  3. 這樣展示的圖片是第2張圖片昙啄,偏移量為320穆役,滑動(dòng)到下一張圖片的時(shí)候,設(shè)置當(dāng)前位置為1梳凛,設(shè)置當(dāng)前數(shù)組圖片為圖片1耿币、圖片2、圖片3韧拒,刷新UI淹接,并且把scrollView的偏移量設(shè)置為320,即展示的圖片永遠(yuǎn)在中間叛溢。
  4. 點(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);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末慢味,一起剝皮案震驚了整個(gè)濱河市场梆,隨后出現(xiàn)的幾起案子墅冷,更是在濱河造成了極大的恐慌,老刑警劉巖或油,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寞忿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡顶岸,警方通過(guò)查閱死者的電腦和手機(jī)腔彰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)辖佣,“玉大人霹抛,你說(shuō)我怎么就攤上這事【硖福” “怎么了杯拐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)世蔗。 經(jīng)常有香客問(wèn)我藕施,道長(zhǎng),這世上最難降的妖魔是什么凸郑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮矛市,結(jié)果婚禮上芙沥,老公的妹妹穿的比我還像新娘。我一直安慰自己浊吏,他們只是感情好而昨,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著找田,像睡著了一般歌憨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上墩衙,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天务嫡,我揣著相機(jī)與錄音,去河邊找鬼漆改。 笑死心铃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挫剑。 我是一名探鬼主播去扣,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼樊破!你這毒婦竟也來(lái)了愉棱?” 一聲冷哼從身側(cè)響起唆铐,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奔滑,沒(méi)想到半個(gè)月后艾岂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡档押,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年澳盐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片令宿。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叼耙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出粒没,到底是詐尸還是另有隱情筛婉,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布癞松,位于F島的核電站爽撒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏响蓉。R本人自食惡果不足惜硕勿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枫甲。 院中可真熱鬧源武,春花似錦、人聲如沸想幻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)脏毯。三九已至闹究,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間食店,已是汗流浹背渣淤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叛买,地道東北人砂代。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像率挣,于是被迫代替她去往敵國(guó)和親刻伊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容