一颊郎、功能
- 調(diào)用該類中的初始化方法后,可以初始化循環(huán)播放圖片的ScrollView霎苗、pageControl姆吭,以及設置自動循環(huán)播放的時間間隔。
- ScrollView可自動循環(huán)播放唁盏,也可以手動滑動ScrollView内狸。當手動滑動ScrollView時,停止自動循環(huán)播放圖片厘擂,直至不再手動滑動圖片時為止昆淡;
- 可手動向右或者向左滑動ScrollView:當從最后一張圖片向右滑動時,進入第一章圖片刽严;當從第一張圖片向左滑動時瘪撇,進入最后一張圖片。
- 可設置ScrollView上的圖片是否可以點擊港庄,并設置點擊實現(xiàn)方法倔既。
- 使用SDWebImage類庫從后臺服務器(或者網(wǎng)絡上)下載圖片。
- 使用蘋果自帶的JSON數(shù)據(jù)解析類NSJSONSerialization來進行json數(shù)據(jù)解析鹏氧。
二渤涌、準備工作
1. 給程序增加SDWebImage依賴
??可以通過cocoaPods安裝SDWebImage依賴,也可以直接前往SDWebImage開源地址將框架下載到本地把还,然后導入到自己的工程中实蓬。
2. 充分明了自己開發(fā)使用的編譯器環(huán)境——即iOS系統(tǒng)版本
??為何要將這一條單獨拉出來說呢?這是因為吊履,從iOS 9(不包含iOS 9)之后安皱,NSURLConnection.h類中從URLRequest中獲取data的如下方法已經(jīng)被棄用了:
NSData *response = [NSURLConnection sendSynchronousRequest:requestURL returningResponse:nil error:nil];
??根據(jù)幫助文檔說明,將使用NSURLSession.h類中的
[NSURLSession dataTaskWithRequest:completionHandler:]
方法作為替代艇炎。所以酌伊,如果要開發(fā)iOS 5~iOS 9的應用程序,可以繼續(xù)使用[NSURLConnection sendSynchronousRequest:returningResponse:error:]方法來獲取數(shù)據(jù);iOS 9之后的應用程序缀踪,則使用[NSURLSession dataTaskWithRequest:completionHandler:]方法來獲取數(shù)據(jù)居砖。
??本篇文章是基于iOS 10.3來寫的虹脯,所以我將采用[NSURLSession dataTaskWithRequest:completionHandler:]來獲取數(shù)據(jù)。
三奏候、代碼及原理
A. SCAutoCircleScrollView.h文件
#import <UIKit/UIKit.h>
typedef enum {
//設置scrollView上的imageView. Dafult is SCAutoCircleScrollViewSelectionTypeTap
SCAutoCircleScrollViewSelectionTypeTap, //Can tap the scrollView to get a detail information or new view
SCAutoCircleScrollViewSelectionTypeNone //Cannot tap the scrollView
}SCAutoCircleScrollViewSelectionType;
@protocol SCAutoCircleScrollViewDelegate <NSObject>
@optional
- (void)autoCircleScrollViewDidClickedAtPage : (NSInteger)pageNumber;
@end
@interface SCAutoCircleScrollView : UIView<UIScrollViewDelegate>
{
NSTimer *timer;
NSArray *scrollViewSourceArray;
NSTimeInterval scheduledtimeInterval;
}
@property (nonatomic, strong) UIScrollView *autoCircleScrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
@property (nonatomic, assign) SCAutoCircleScrollViewSelectionType autoCircleScrollViewSelectionType;
@property (nonatomic, assign) id <SCAutoCircleScrollViewDelegate> autoCircleScrollViewDelegate;
- (id)initThePageControlOnScrollViewWithFrame : (CGRect)pageControlFrame andAutoCircleScrollViewWithFrame : (CGRect)scrollViewFrame withViewsArray : (NSArray*)viewsArray withTimeInterval : (NSTimeInterval)timeInterval;
@end
B. SCAutoCircleScrollView.h文件說明
typedef enum {
SCAutoCircleScrollViewSelectionTypeTap,
SCAutoCircleScrollViewSelectionTypeNone
}SCAutoCircleScrollViewSelectionType;
??因為我是將實現(xiàn)自動循環(huán)的類給封裝了循集,便于在其它類中調(diào)用,所以蔗草,我們需要設置一個標簽咒彤,用于表示scrollView是否可以被點擊。使用enum(枚舉)是一個設置狀態(tài)標簽的比較好的方法咒精。
@protocol SCAutoCircleScrollViewDelegate <NSObject>
@optional
- (void)autoCircleScrollViewDidClickedAtPage : (NSInteger)pageNumber;
@end
??因為設置了ScrollView是否可以點擊镶柱,如果可以點擊,則實現(xiàn)點擊方法狠轻。使用代理來設置這一方法。因為用戶也有可能設置ScrollView不可點擊彬犯,所以將該方法設置為可選的(@optional)向楼,這樣,只有當真正需要實現(xiàn)該方法時才去實現(xiàn)它谐区。
??接下來湖蜕,就是定義一些變量和接口,都是很常規(guī)的方法宋列,此處不再贅述昭抒。如有疑問,可以留言給我炼杖,我將盡力解答灭返。
我們在.h文件中定義的實例和方法,都是公有的坤邪,可以在調(diào)用這個接口的類中通過這個接口的實例來調(diào)用這些實例和方法但通常情況下熙含,我們可能并不希望這樣做,而只是調(diào)用該調(diào)用的方法艇纺,所以可以考慮將除了
@property (nonatomic, assign) SCAutoCircleScrollViewSelectionType autoCircleScrollViewSelectionType; @property (nonatomic, assign) id <SCAutoCircleScrollViewDelegate> autoCircleScrollViewDelegate;
這兩個定義之外的其它定義放到SCAutoCircleScrollView.m文件中怎静,將其變?yōu)樗接小?/p>
??最后,我們定義這個接口中的公有方法黔衡,通過在其它類中實例化這個接口之后蚓聘,通過實例化的類來調(diào)用該方法,以初始化相關(guān)的界面:
- (id)initThePageControlOnScrollViewWithFrame : (CGRect)pageControlFrame andAutoCircleScrollViewWithFrame : (CGRect)scrollViewFrame withViewsArray : (NSArray*)viewsArray withTimeInterval : (NSTimeInterval)timeInterval;
??這是一個實例方法盟劫,所以只能通過實例對象來調(diào)用夜牡。
C. SCAutoCircleScrollView.m文件
#import "SCAutoCircleScrollView.h"
#import <SDWebImage/UIImageView+WebCache.h>
@implementation SCAutoCircleScrollView
- (id)initThePageControlOnScrollViewWithFrame : (CGRect)pageControlFrame andAutoCircleScrollViewWithFrame : (CGRect)scrollViewFrame withViewsArray : (NSArray*)viewsArray withTimeInterval : (NSTimeInterval)timeInterval {
self = [super initWithFrame:scrollViewFrame];
if(self) {
_autoCircleScrollViewSelectionType = SCAutoCircleScrollViewSelectionTypeTap;
scrollViewSourceArray = viewsArray;
scheduledtimeInterval = timeInterval;
self.userInteractionEnabled = YES;
[self initPageControlWithFrame:pageControlFrame andScrollViewsWithFrame:scrollViewFrame];
}
return self;
}
- (void)initPageControlWithFrame : (CGRect)pageControlFrame andScrollViewsWithFrame: (CGRect)scrollViewFrame {
CGFloat scrollViewWidth = scrollViewFrame.size.width;
CGFloat scrollViewHeight = scrollViewFrame.size.height;
//初始化ScrollView
_autoCircleScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
_autoCircleScrollView.delegate = self;
_autoCircleScrollView.showsVerticalScrollIndicator = NO;
_autoCircleScrollView.showsHorizontalScrollIndicator = NO;
_autoCircleScrollView.pagingEnabled = YES;
_autoCircleScrollView.contentSize = CGSizeMake(([scrollViewSourceArray count] +2 ) * scrollViewWidth, scrollViewHeight);
[self addSubview:_autoCircleScrollView];
//將要自動循環(huán)的視圖(UIImageView)添加到ScrollView上
UIImageView *firstImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
[firstImageView sd_setImageWithURL:[NSURL URLWithString:[scrollViewSourceArray lastObject]]
placeholderImage:nil];
[_autoCircleScrollView addSubview:firstImageView];
for (int i = 0; i < [scrollViewSourceArray count]; i++) {
UIImageView *imageview = [[UIImageView alloc]initWithFrame:CGRectMake((i+1)*scrollViewWidth, 0, scrollViewWidth, scrollViewHeight)];
[imageview sd_setImageWithURL:[NSURL URLWithString:[scrollViewSourceArray objectAtIndex:i]]
placeholderImage:nil];
[_autoCircleScrollView addSubview:imageview];
}
UIImageView *lastImageView = [[UIImageView alloc]initWithFrame:CGRectMake(scrollViewWidth*(scrollViewSourceArray.count+1), 0, scrollViewWidth, scrollViewHeight)];
[lastImageView sd_setImageWithURL:[NSURL URLWithString:[scrollViewSourceArray objectAtIndex:0]] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
//初始化pageControl
_pageControl = [[UIPageControl alloc]initWithFrame:pageControlFrame];
_pageControl.numberOfPages = scrollViewSourceArray.count;
_pageControl.currentPage = 0;
_pageControl.enabled = YES;
_pageControl.currentPageIndicatorTintColor = [UIColor redColor];
_pageControl.pageIndicatorTintColor = [UIColor whiteColor];
[self addSubview:_pageControl];
[_autoCircleScrollView addSubview:lastImageView];
timer = [NSTimer scheduledTimerWithTimeInterval:scheduledtimeInterval target:self selector:@selector(scrollToNextPageAutomatically:) userInfo:nil repeats:YES];
}];
//初始化時,將scrollView上的view設置為第一個view
[_autoCircleScrollView scrollRectToVisible:CGRectMake(scrollViewWidth, 0, scrollViewWidth, scrollViewHeight) animated:NO];
//添加一個點擊手勢侣签,如果ScrollView設置的是可以點擊狀態(tài)氯材,則觸發(fā)響應的方法
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTheScrollView:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[self addGestureRecognizer:tap];
}
-(void)scrollToNextPageAutomatically:(id)sender
{
//工作原理:
//1. 首先渣锦,判斷scrollView當前在第幾頁,此時可以通過計算scrollView的content的偏移量來協(xié)助確認:如果“偏移量/pageWidth”的值是0氢哮,說明當前scrollView的x坐標值為0袋毙,對應的是最后一張圖像,那么當前pageControl.currentPage的值是最后一個(views的數(shù)量-1冗尤,因為pageControl的值是從0開始的听盖,下同);如果“偏移量/pageWidth”的值是“views數(shù)量+1”裂七,說明當前scrollview顯示的是第一張圖片皆看,那么當前pageControl.currentPage的值是0;其它情況是“偏移量/pageWidth” - 1.
//2. 然后背零,根據(jù)_pageControl.currentPage的值腰吟,我們將scrollView滾動到下一張圖上,這個通過設置“[_autoCircleScrollView scrollRectToVisible:rect animated:YES];”的方法來實現(xiàn)徙瓶,并同時增加currentPageNumber的值(currentPageNumber的初始值為當前pageControl.currentPage的值)毛雇。
//3. 最后,如果pageControl.currentPage的值為views的數(shù)量侦镇,那么從第一張圖開始循環(huán)灵疮,并設置currentPageNumber的值為0.
CGFloat pageWidth = _autoCircleScrollView.frame.size.width;
int currentPage = _autoCircleScrollView.contentOffset.x/pageWidth;
if (currentPage == 0) {
_pageControl.currentPage = scrollViewSourceArray.count-1;
}else if (currentPage == scrollViewSourceArray.count+1) {
_pageControl.currentPage = 0;
}else {
_pageControl.currentPage = currentPage-1;
}
long currentPageNumber = _pageControl.currentPage;
CGSize viewSize = _autoCircleScrollView.frame.size;
CGRect rect = CGRectMake((currentPageNumber+2)*pageWidth, 0, viewSize.width, viewSize.height);
[_autoCircleScrollView scrollRectToVisible:rect animated:YES];
currentPageNumber++;
if (currentPageNumber == scrollViewSourceArray.count) {
_autoCircleScrollView.contentOffset = CGPointMake(0, 0);
currentPageNumber = 0;
}
self.pageControl.currentPage = currentPageNumber;
}
//點擊scrollView時觸發(fā)
- (void)tapTheScrollView:(UITapGestureRecognizer *)tapGesture
{
if (_autoCircleScrollViewSelectionType != SCAutoCircleScrollViewSelectionTypeTap) {
return;
}
if (_autoCircleScrollViewDelegate && [_autoCircleScrollViewDelegate respondsToSelector:@selector(autoCircleScrollViewDidClickedAtPage:)]) {
[_autoCircleScrollViewDelegate autoCircleScrollViewDidClickedAtPage:_pageControl.currentPage];
}
}
#pragma mark---- UIScrollView delegate methods
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
//開始拖動scrollview的時候 停止計時器控制的跳轉(zhuǎn)
[timer invalidate];
timer = nil;
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat width = _autoCircleScrollView.frame.size.width;
CGFloat height = _autoCircleScrollView.frame.size.height;
//當手指滑動scrollview,而scrollview減速停止的時候 開始計算當前的圖片的位置
int currentPage = _autoCircleScrollView.contentOffset.x/width;
if (currentPage == 0) {
_autoCircleScrollView.contentOffset = CGPointMake(width * scrollViewSourceArray.count, 0);
[_autoCircleScrollView scrollRectToVisible:CGRectMake(scrollViewSourceArray.count * width, 0, width, height) animated:YES];
_pageControl.currentPage = scrollViewSourceArray.count-1;
}else if (currentPage == scrollViewSourceArray.count+1) {
_autoCircleScrollView.contentOffset = CGPointMake(width, 0);
[_autoCircleScrollView scrollRectToVisible:CGRectMake(width, 0, width, height) animated:YES];
_pageControl.currentPage = 0;
}else {
_pageControl.currentPage = currentPage-1;
}
//拖動完畢的時候 重新開始計時器控制跳轉(zhuǎn)
timer = [NSTimer scheduledTimerWithTimeInterval:scheduledtimeInterval target:self selector:@selector(scrollToNextPageAutomatically:) userInfo:nil repeats:YES];
}
@end
D. SCAutoCircleScrollView.m文件說明及功能實現(xiàn)原理
??下面壳繁,就是本文的重頭戲之一——使用UIScrollView完成圖片的自動循環(huán)播放及手動滑動震捣。
1. 實現(xiàn)自動循環(huán)的原理
??為了實現(xiàn)在一個ScrollView上自動循環(huán)播放多張圖片,我們需要將顯示這些圖片的UIImageView都添加到ScrollView上闹炉,ImageView的長與寬需要與ScrollView的長與寬保持一致蒿赢。如圖1所示:
??所謂的自動循環(huán)播放(設置為從左到右自動滑動),就是當播放到最后一張圖片時渣触,依然按照從左到右的方向進入第一張圖片诉植,而不是先向左滑動到第一張圖片(中間會經(jīng)過第一張圖片和最后一張圖片之間的所有圖片,體驗感非常不好)昵观。
??當手動滑動時ScrollView時晾腔,當從第一張圖片往左滑動時,能進入最后一張圖片啊犬;而從最后一張圖片往右滑動時灼擂,直接進入第一張圖片。
??為了完成上述兩個功能觉至,我們需要在ScrollView上添加“圖片數(shù)量+2”個ImageView剔应。比如,我需要使用ScrollView循環(huán)播放4張圖片,則我需要在ScrolLView上添加6個UIImageView.如圖2所示峻贮。
??下面詳細說明一下如此做的原因:
- 按照順序創(chuàng)建ScrollView上的ImageView席怪,一共創(chuàng)建6個——ImageView1~ImageView6;
- ImageView1放置圖片4纤控,Image2Image5放置圖片1圖片4挂捻,ImageView6放置圖片1。這樣做的目的是:當我們從圖片1往左滑動時船万,顯示的就是圖片4刻撒;當從圖片4往右手動滑動或者自動滑動時,顯示的是圖片1.
??綜上兩點耿导,我們要做的工作其實就是如何從圖片1——>圖片4声怔,以及從圖片4——>圖片1。
??在SCAutoCircleScrollView.m文件中舱呻,我們先實現(xiàn)SCAutoCircleScrollView.h定義的對外接口的初始化方法“- (id)initThePageControlOnScrollViewWithFrame : (CGRect)pageControlFrame andAutoCircleScrollViewWithFrame : (CGRect)scrollViewFrame withViewsArray : (NSArray*)viewsArray withTimeInterval : (NSTimeInterval)timeInterval”醋火。在這里,我們將外部定義的相關(guān)控件的frame箱吕、含有圖片地址的數(shù)組和自動循環(huán)播放的時間間隔傳遞進來芥驳,并依次在“- (void)initPageControlWithFrame : (CGRect)pageControlFrame andScrollViewsWithFrame: (CGRect)scrollViewFrame”方法中初始化ScrollView、PageControl和ImageView殖氏。接下來我們就重點講一下“- (void)initPageControlWithFrame : (CGRect)pageControlFrame andScrollViewsWithFrame: (CGRect)scrollViewFrame”里面的方法晚树。
- 初始化ScrollView
_autoCircleScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)]; _autoCircleScrollView.delegate = self; _autoCircleScrollView.showsVerticalScrollIndicator = NO; _autoCircleScrollView.showsHorizontalScrollIndicator = NO; _autoCircleScrollView.pagingEnabled = YES; _autoCircleScrollView.contentSize = CGSizeMake(([scrollViewSourceArray count] +2 ) * scrollViewWidth, scrollViewHeight);
??這是一個很常規(guī)的初始流程:設置frame——>設置delegate——>設置是否顯示水平和豎直滾動條——>設置是否分頁顯示(pagingEnabled的值設置為YES姻采,一次滾動一張圖片的范圍)——>設置ScrollView的ContentSize(ContentSize表示scrollView顯示的整個長度和寬度)雅采。
- 初始化ImageView、pageControl和timer
??接下來慨亲,我們要初始化ImageView并將其加到ScrollView上婚瓜。添加ImageView1~ImageView5的方法類似,此處只按照添加ImageView1的方法講解:
UIImageView *firstImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
[firstImageView sd_setImageWithURL:[NSURL URLWithString:[scrollViewSourceArray lastObject]]
placeholderImage:nil];
[_autoCircleScrollView addSubview:firstImageView];
??首先初始化一個ImageView刑棵,然后使用SDWebImage中的“ sd_setImageWithURL:placeholderImage:”方法巴刻,將從網(wǎng)絡上下載下來的圖片放在這個ImageView上,然后將該ImageView添加到ScrollView上蛉签。placeholderImage:參數(shù)放的是如果圖片下載不成功的時候的占位圖片胡陪。按照上面的描述,我們在ImageView1上放的是最后一張照片碍舍,所以我獲取的是scrollViewSourceArray數(shù)組中的最后一個元素柠座。
??對于常規(guī)的情況(比如在tableView中設置默認的cell.image的圖片時),使用“ sd_setImageWithURL:placeholderImage:”方法下載圖片沒有問題片橡。但是如果在scrollView上的ImageView中使用該方法時妈经,會出現(xiàn)一個問題——當加載完頁面之后,pageControl不能被很好的初始化,同時scrollView也不會自動循環(huán)播放吹泡,需要等一段時間之后骤星,pageControl磁能被初始化好,而且只有先手動滑動一下scrollView爆哑,然后scrollView才會自動循環(huán)播放洞难。經(jīng)過多方嘗試,我們將ImageVeiw6的初始化方法修改成如下方法泪漂,就可以解決這個問題廊营。具體原因我還沒有想明白,如果有哪位朋友了解萝勤,還請不吝賜教露筒。
UIImageView *lastImageView = [[UIImageView alloc]initWithFrame:CGRectMake(scrollViewWidth*(scrollViewSourceArray.count+1), 0, scrollViewWidth, scrollViewHeight)];
[lastImageView sd_setImageWithURL:[NSURL URLWithString:[scrollViewSourceArray objectAtIndex:0]] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
//初始化pageControl
_pageControl = [[UIPageControl alloc]initWithFrame:pageControlFrame];
_pageControl.numberOfPages = scrollViewSourceArray.count;
_pageControl.currentPage = 0;
_pageControl.enabled = YES;
_pageControl.currentPageIndicatorTintColor = [UIColor redColor];
_pageControl.pageIndicatorTintColor = [UIColor whiteColor];
[self addSubview:_pageControl];
[_autoCircleScrollView addSubview:lastImageView];
timer = [NSTimer scheduledTimerWithTimeInterval:scheduledtimeInterval target:self selector:@selector(scrollToNextPageAutomatically:) userInfo:nil repeats:YES];
}];
??我們在下載圖片1時,使用SDWebImage中的“sd_setImageWithURL:placeholderImage:completed:”方法敌卓,同時將pageControl的初始化方法慎式、定時器timer的初始化方法、將ImageView6放到ScrollView上的方法都放到completed:塊中編寫趟径。
??關(guān)于pageControl的初始化瘪吏,首先設置其frame,然后設置pageControl要顯示的頁數(shù)(即圖片的總數(shù)量)蜗巧,并設置頁面初始化時pageControl的初始值(第一張圖片對應的是0)掌眠,然后設置pageControl的相關(guān)顏色——currentPageIndicatorTintColor表示的是當前被選擇時的顏色,pageIndicatorTintColor指的是未被選擇的顏色幕屹。
??最后蓝丙,我們設置ScrollView剛被初始化時顯示哪一張圖片(scrollRectToVisible:方法表示顯示的是scrollView的那個width和height,我們還會在后面使用到它望拖。因為我們希望初始化scrollView時顯示圖片1渺尘,而圖片1是被加在ImageView2上的,所以設置width和height為CGRectMake(scrollViewWidth, 0, scrollViewWidth, scrollViewHeight))说敏,并添加一個點擊手勢鸥跟。
//初始化時,將scrollView上的view設置為第一個view
[_autoCircleScrollView scrollRectToVisible:CGRectMake(scrollViewWidth, 0, scrollViewWidth, scrollViewHeight) animated:NO];
//添加一個點擊手勢盔沫,如果ScrollView設置的是可以點擊狀態(tài)医咨,則觸發(fā)響應的方法
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTheScrollView:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[self addGestureRecognizer:tap];
- 在scrollToNextPageAutomatically:方法中實現(xiàn)scrollView的自動循環(huán)播放
??實現(xiàn)自動循環(huán)播放的原理如下:
a) 首先,判斷scrollView當前在第幾頁架诞,此時可以通過計算scrollView的content的偏移量來協(xié)助確認:如果“偏移量/pageWidth”的值是0拟淮,說明當前scrollView的x坐標值為0,對應的是最后一張圖像侈贷,那么當前pageControl.currentPage的值是最后一個(views的數(shù)量-1惩歉,因為pageControl的值是從0開始的等脂,下同);如果“偏移量/pageWidth”的值是“views數(shù)量+1”撑蚌,說明當前scrollview顯示的是第一張圖片上遥,那么當前pageControl.currentPage的值是0;其它情況是“偏移量/pageWidth” - 1.
b) 然后争涌,根據(jù)_pageControl.currentPage的值粉楚,我們將scrollView滾動到下一張圖上,這個通過設置“[_autoCircleScrollView scrollRectToVisible:rect animated:YES];”的方法來實現(xiàn)亮垫,并同時增加currentPageNumber的值(currentPageNumber的初始值為當前pageControl.currentPage的值)模软。
c) 最后,如果pageControl.currentPage的值為views的數(shù)量饮潦,那么從第一張圖開始循環(huán)燃异,并設置pageControl的currentPageNumber的值為0.
??我們在如下的代碼中完成原理a)的工作:
CGFloat pageWidth = _autoCircleScrollView.frame.size.width;
int currentPage = _autoCircleScrollView.contentOffset.x/pageWidth;
if (currentPage == 0) {
_pageControl.currentPage = scrollViewSourceArray.count-1;
}else if (currentPage == scrollViewSourceArray.count+1) {
_pageControl.currentPage = 0;
}else {
_pageControl.currentPage = currentPage-1;
}
??然后,在如下代碼中完成原理b)的工作继蜡。
long currentPageNumber = _pageControl.currentPage;
CGSize viewSize = _autoCircleScrollView.frame.size;
CGRect rect = CGRectMake((currentPageNumber+2)*pageWidth, 0, viewSize.width, viewSize.height);
[_autoCircleScrollView scrollRectToVisible:rect animated:YES];
currentPageNumber++;
??最后回俐,在如下代碼中完成原理c)的工作。
if (currentPageNumber == scrollViewSourceArray.count) {
_autoCircleScrollView.contentOffset = CGPointMake(0, 0);
currentPageNumber = 0;
}
self.pageControl.currentPage = currentPageNumber;
- 使用UIScrollViewDelegate協(xié)議中的方法實現(xiàn)scrollView手動滑動
??首先稀并,當即將滑動scrollView時仅颇,先終止timer的運行,這樣可以防止手動滑動與自動循環(huán)同時進行碘举,會造成ImageView的突變:
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[timer invalidate];
timer = nil;
}
??然后忘瓦,計算當前顯示的是第幾張圖片,使用如下的方法:
int currentPage = _autoCircleScrollView.contentOffset.x/width;
??如果currentPage的值是0引颈,說明當前是在ImageView1耕皮,對應圖片4,則我們就將scrollView的
contentOffset設置為圖片4對應的值线欲,并將scrollRectToVisible:設置為顯示圖片4明场,pageControl.currentPage也設置為圖片4對應的頁面(即3)汽摹。
??如果currentPage的值是“圖片數(shù)量+1”李丰,說明當前是在ImageView6,對應圖片1逼泣,則我們就將將scrollView的
contentOffset設置為圖片1對應的值趴泌,并將scrollRectToVisible:設置為顯示圖片1,pageControl.currentPage也設置為圖片1對應的頁面(即0)拉庶。
??如果currentPage的值不是0或者“圖片數(shù)量+1”嗜憔,就正常設置pageControl.currentPage的值即可。
??最后氏仗,當不再手動滑動時吉捶,重啟timer。
E. ViewController.m文件實現(xiàn)從后臺獲取的數(shù)據(jù)的json解析,并初始化scrollView
//json解析
NSURLRequest *requestURL = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1/exerciseAutoScrollView/exerciseAutoScrollView.php"]];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestURL
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:[[NSData alloc]
initWithData:data]
options:NSJSONReadingMutableContainers
error:nil];
//NSDictionary *weatherInfo = [jsonData objectForKey:@"IMG_003"];
NSArray *arr = [[NSArray alloc]initWithArray:[jsonData allKeys]];
// NSLog(@"arr里面的內(nèi)容為--》%@", [weatherInfo objectForKey:@"location"]);
NSLog(@"arr里面的內(nèi)容為--》%@", arr);
NSMutableArray *textArr = [[NSMutableArray alloc]initWithCapacity:10];
for(int i =0; i < [arr count]; i++) {
NSDictionary *imageDataInfoDic = [jsonData objectForKey:[arr objectAtIndex:i]];
[textArr addObject:[imageDataInfoDic objectForKey:@"location"]];
}
}];
// 使用resume方法啟動任務
[dataTask resume];
??iOS 9之后呐舔,使用系統(tǒng)自帶的框架進行json解析使用如下步驟:
a) 獲取URLRequest(NSURLRequest的實例)币励;
b) 獲取session(NSURLSession的實例);
c) 獲取data(NSURLSessionDataTask的實例珊拼,采用“dataTaskWithRequest:completionHandler:”方法)食呻;
d) 在completionHandler塊中,編寫代碼獲取json數(shù)據(jù)(數(shù)據(jù)是NSDictionary類型澎现,采用“[NSJSONSerialization JSONObjectWithData:[[NSData alloc] initWithData:data] options:NSJSONReadingMutableContainers error:error])”方法獲取);
e) 最后仅胞,采用“[dataTask resume];”方法開啟任務。其中剑辫,datatask為上文創(chuàng)建的NSURLSessionDataTask的實例干旧。
??在“dataTaskWithRequest:completionHandler:”方法的completionHandler塊中,當進行完json解析并獲取到數(shù)據(jù)之后妹蔽,就將數(shù)據(jù)保存到數(shù)組中(我解析出來的是4張圖片在遠程服務器的地址)莱革,然后初始化自動循環(huán)的scrollView:
sourceArray = [[NSArray alloc]initWithArray:textArr];
SCAutoCircleScrollView *scrollView = [[SCAutoCircleScrollView alloc]initThePageControlOnScrollViewWithFrame:CGRectMake(deviceScreenWidth / 2, 100, deviceScreenWidth / 2, 30) andAutoCircleScrollViewWithFrame:CGRectMake(0, 0, deviceScreenWidth, 130) withViewsArray:sourceArray withTimeInterval : 2.0];
scrollView.autoCircleScrollViewDelegate = self;
[self.view addSubview:scrollView];
四、后記
??我已經(jīng)本文的實例代碼上傳到github上讹开,讀者可前往github自行下載實例代碼盅视。本文講述的是我基于自己的后臺獲取數(shù)據(jù)的情況,所以讀者朋友們?nèi)绻苯舆\行實例代碼會出錯旦万,建議使用自己的后臺(如何在Mac OS上搭建自己的后臺闹击?請參考iOS網(wǎng)絡開發(fā)之一——Mac上搭建并配置PHP+Apache+Mysql這篇文章〕伤遥或者修改“dataTaskWithRequest:completionHandler:”方法的completionHandler塊中的json數(shù)據(jù)獲取來源赏半,比如從百度圖片上找一些圖片地址等)。
??同時淆两,我也用hexo+github page的方法搭建了一個個人博客断箫,未來一些文章我也將同步發(fā)布到該博客上,感興趣的朋友可以關(guān)注一下秋冰,給點支持和建議仲义,謝謝。