輪播圖在開發(fā)中經(jīng)常用到。并且面試的時(shí)候也經(jīng)?;貑柕?。
其實(shí)最長問道的也就兩點(diǎn)
1、內(nèi)存優(yōu)化
2、計(jì)時(shí)器問題
3、輪播實(shí)現(xiàn)方案
此輪播圖以UIScrollView實(shí)現(xiàn)
先以第一點(diǎn)內(nèi)存優(yōu)化和實(shí)現(xiàn)方案來講,如何去做內(nèi)存優(yōu)化?
圖片在iOS設(shè)備中很占內(nèi)存,所以每當(dāng)遇到加載圖片的時(shí)候需要格外注意,不要去加載一些不必要的圖片。
首先應(yīng)當(dāng)想到要減少UIImageView在UIScrollView上加載。結(jié)合UITableView的特點(diǎn):復(fù)用。所以至少應(yīng)當(dāng)創(chuàng)建三個(gè)UIImageView。

實(shí)際上我們所展示的第1張圖片在對(duì)應(yīng)的ScrollView上應(yīng)該是第2頁。
并且重要的一點(diǎn)就是:所展示的圖片一直是中間的。當(dāng)滑到兩邊的圖片后,要立刻重置到第二張。
兩種代理實(shí)現(xiàn)方案
減速實(shí)現(xiàn)
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
滑動(dòng)過程中
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
當(dāng)使用結(jié)束拖拽的代理正常使用情況下其實(shí)是不會(huì)出現(xiàn)的問題的,但是當(dāng)用戶快速拖拽時(shí),scrollview的偏移會(huì)出現(xiàn)問題。最好的方法便是實(shí)時(shí)計(jì)算偏移量
核心代碼
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self reloadIndex];
}
//滑到中心,切記不能調(diào)用該動(dòng)畫,否則會(huì)觸發(fā)代理
- (void)scrollCenter
{
[self.mainScrollView setContentOffset:CGPointMake(CGRectGetWidth(self.mainScrollView.bounds), 0)];
if (self.indexBack) {
self.indexBack(self.index);
}
}
//計(jì)算頁數(shù)
- (void)reloadIndex
{
if (self.imageArray && self.imageArray.count > 0)
{
CGFloat pointX = self.mainScrollView.contentOffset.x;
//此處的value用于邊緣判斷,當(dāng)imageview距離兩邊間距小于1時(shí),觸發(fā)偏移
CGFloat Value = 0.2f;
if (pointX > 2 * CGRectGetWidth(self.mainScrollView.bounds) - Value) {
self.index = (self.index + 1) % self.imageArray.count;
} else if (pointX < Value) {
self.index = (self.index + self.imageArray.count - 1) % self.imageArray.count;
}
}
}
//重寫index的set方法
- (void)setIndex:(NSInteger)index
{
_index = index;
NSInteger totalCount = self.imageArray.count;
NSInteger leftIndex = (self.index+totalCount-1)%totalCount;
NSInteger rightIndex = (self.index+1)%totalCount;
[self.leftImageView setImage:[UIImage imageNamed:self.imageArray[leftIndex]]];
[self.midImageView setImage:[UIImage imageNamed:self.imageArray[self.index]]];
[self.rightImageView setImage:[UIImage imageNamed:self.imageArray[rightIndex]]];
[self scrollCenter];
}
關(guān)于計(jì)算頁數(shù)說明:
假如有4張圖片排序?yàn)椋?|0|1|2|3,其實(shí)嚴(yán)格說此排序像一個(gè)環(huán)形數(shù)列,所以leftIndex和rightIndex的公式相當(dāng)于去計(jì)算指定頁數(shù)的前一個(gè)和后一個(gè)數(shù)字
.h 文件
@interface MCScrollView : UIView
@property (nonatomic, copy) void(^indexBack)(NSInteger pageIndex); //頁數(shù)回調(diào)
@property (nonatomic, copy) NSArray *imageArray; //存儲(chǔ)圖片數(shù)據(jù)
@property (nonatomic, assign) NSInteger index; //當(dāng)前第幾頁,默認(rèn)為0(0為第一頁,如果制定頁數(shù)需要加1)
@end
定時(shí)器添加
.h文件添加
@property (nonatomic, assign) NSTimeInterval duration; //時(shí)長
實(shí)現(xiàn)
- (void)setDuration:(NSTimeInterval)duration
{
_duration = duration;
if (duration > 0.0) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:duration target:self selector:@selector(changeNext) userInfo:nil repeats:YES];
[self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:duration]];
}
}
- (void)changeNext
{
[self.mainScrollView setContentOffset:CGPointMake(2*CGRectGetWidth(self.mainScrollView.bounds), 0) animated:YES];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.timer setFireDate:[NSDate distantFuture]];
//[NSDate distantFuture]表示暫停計(jì)時(shí)
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:self.duration]];
//
}
[NSDate dateWithTimeIntervalSinceNow:self.duration]表示在當(dāng)前時(shí)間的幾秒后開始計(jì)時(shí),優(yōu)點(diǎn)是不會(huì)立即執(zhí)行計(jì)時(shí)器
Demo地址:https://github.com/HeartbeatT/MCScrollView.git