iOS 輪播圖

先看看效果.gif
#import <UIKit/UIKit.h>
@class CarouselFigureView;
typedef NS_ENUM(NSInteger,CarouselFigureViewDirection) {
    CarouselFigureViewDirection_Left,    // 向左
    CarouselFigureViewDirection_Right    // 向右
};
@protocol CarouselFigureViewDataSource <NSObject>
@required
/*
 * 功能:返回顯示cell的個(gè)數(shù)
 * 參數(shù)carouselFigureView:當(dāng)前滾動(dòng)視圖
 * 返回:返回滾動(dòng)視圖cell的個(gè)數(shù)
 */
- (NSInteger)numberOfCellInCarouselFigureView:(UIView *)carouselFigureView;
/*
 * 功能:返回每個(gè)cell的內(nèi)容
 * 參數(shù)carouselFigureView:當(dāng)前滾動(dòng)視圖
 * 參數(shù)index:每個(gè)滾動(dòng)cell的下標(biāo)
 * 返回:返回每個(gè)cell上的視圖
 */
- (UIView *)carouselFigureView:(UIView *)carouselFigureView cellForIndex:(NSInteger)index;
@optional
/*
 * 功能:返回定時(shí)滾動(dòng)的時(shí)間,默認(rèn)是3秒
 * 參數(shù)carouselFigureView:當(dāng)前滾動(dòng)視圖
 * 返回:返回每次滾動(dòng)的時(shí)間間隔
 */
- (NSTimeInterval)timeIntervalForScrollInCarouselFigureView:(UIView *)carouselFigureView;
/*
 * 功能:返回滾動(dòng)方向,默認(rèn)是向右
 * 參數(shù)carouselFigureView:當(dāng)前滾動(dòng)視圖
 * 返回:返回滾動(dòng)視圖的方向
 */
- (CarouselFigureViewDirection)directionForScrollInCarouselFigureView:(UIView *)carouselFigureView;
/*
 * 功能:設(shè)置下標(biāo)視圖樣式
 * 參數(shù)carouselFigureView:當(dāng)前滾動(dòng)視圖
 * 參數(shù)pageControl:滾動(dòng)下標(biāo)(可以在此修改滾動(dòng)下標(biāo)的樣式)
 */
- (void)carouselFigureView:(UIView *)carouselFigureView pageControl:(UIPageControl *)pageControl;
@end
@protocol CarouselFigureViewDelegate <NSObject>
@optional
/*
 * 功能:當(dāng)點(diǎn)擊某個(gè)cell時(shí),觸發(fā)的方法回調(diào)
 * 參數(shù)carouselFigureView:當(dāng)前滾動(dòng)視圖
 * 參數(shù)index:點(diǎn)擊cell的下標(biāo)
 */
- (void)carouselFigureView:(UIView *)carouselFigureView didSelectCell:(NSInteger)index;
@end
@interface CarouselFigureView :UIView
/*
 * 功能:數(shù)據(jù)源代理
 */
@property (nonatomic,assign)id<CarouselFigureViewDataSource> dataSource;
/*
 * 功能:響應(yīng)事件代理
 */
@property (nonatomic,assign)id<CarouselFigureViewDelegate> delegate;
@end
#import "CarouselFigureView.h"
#define KPageConrolHeight 30
#define KTimeInterval 3
@interface CarouselFigureView ()<UIScrollViewDelegate>
@property (nonatomic,strong)UIScrollView *scrollView;
@property (nonatomic,strong)UIPageControl *pageControl;
@property (nonatomic,strong)NSTimer *timer;
@end
@implementation CarouselFigureView
// 懶加載scrollView
- (UIScrollView *)scrollView{
    if (!_scrollView) {
        self.scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
        _scrollView.pagingEnabled = YES;
        _scrollView.showsHorizontalScrollIndicator = NO;
        _scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.frame) * ([self numberOfCell] + 2), CGRectGetHeight(self.frame));
        _scrollView.delegate = self;
        _scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.frame), 0);
        // 添加滾動(dòng)視圖
        [self addScrollSubviews];
    }
    return _scrollView;
}
// 給ScrollView添加子視圖
- (void)addScrollSubviews{
    NSInteger num = [self numberOfCell];
    NSMutableArray *ary = [NSMutableArray array];
    for (int i = 0; i < num; i++) {
        UIView *view = [self cellViewForIndex:i];
        [ary addObject:view];
    }
    UIView *firstView = [self cellViewForIndex:0];
    UIView *lastView = [self cellViewForIndex:num - 1];
    [ary addObject:firstView];
    [ary insertObject:lastView atIndex:0];
    [ary enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        CGRect frame = CGRectMake(CGRectGetWidth(self.frame) * idx, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
        ((UIView *)obj).frame = frame;
        [self.scrollView addSubview:((UIView *)obj)];
    }];
}
// 懶加載pageControl
- (UIPageControl *)pageControl{
    if (!_pageControl) {
        self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.frame) - KPageConrolHeight, CGRectGetWidth(self.frame), KPageConrolHeight)];
        if (self.dataSource && [self.dataSource respondsToSelector:@selector(carouselFigureView:pageControl:)]) {
            [self.dataSource carouselFigureView:self pageControl:_pageControl];
        }
        if (!_pageControl.backgroundColor) {
            _pageControl.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5];
        }
        _pageControl.numberOfPages = [self numberOfCell];
        _pageControl.currentPage = 0;
    }
    return _pageControl;
}
// 重寫dataSource的setter方法
- (void)setDataSource:(id<CarouselFigureViewDataSource>)dataSource{
    if (!dataSource) {return;}
    _dataSource = dataSource;
    // 加載子視圖
    [self customSubViews];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:[self timeInterval] target:self selector:@selector(timeAction) userInfo:nil repeats:YES];
}
- (void)timeAction{
    CGPoint point = self.scrollView.contentOffset;
    switch ([self direction]) {
        case CarouselFigureViewDirection_Right:
            point.x += CGRectGetWidth(self.frame);
            break;
        case CarouselFigureViewDirection_Left:
            point.x -= CGRectGetWidth(self.frame);
            break;
        default:
            break;
    }
    [UIView beginAnimations:nil context:nil];
    self.scrollView.contentOffset = point;
    [UIView commitAnimations];
    NSInteger num = [self numberOfCell];
    NSInteger index = self.scrollView.contentOffset.x / CGRectGetWidth(self.frame);
    if (index == 0) {
        self.scrollView.contentOffset = CGPointMake(5 * CGRectGetWidth(self.frame), 0);
    }else if (index == (num + 1)) {
        self.scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.frame), 0);
    }
    self.pageControl.currentPage = (self.scrollView.contentOffset.x - CGRectGetWidth(self.frame)) / CGRectGetWidth(self.frame);
}
// 加載子視圖
- (void)customSubViews{
    [self addSubview:self.scrollView];
    [self addSubview:self.pageControl];
    [self addGesture];
}
// 添加輕拍手勢(shì)
- (void)addGesture{
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognizerAction:)];
    [self addGestureRecognizer:gesture];
}
// 輕拍手勢(shì)觸發(fā)函數(shù)
- (void)tapGestureRecognizerAction:(UITapGestureRecognizer *)sender{
    if (self.delegate && [self.delegate respondsToSelector:@selector(carouselFigureView:didSelectCell:)]) {
        NSInteger index = self.scrollView.contentOffset.x / CGRectGetWidth(self.frame);
        [self.delegate carouselFigureView:self didSelectCell:index - 1];
    }
}
#pragma mark - UIScrollViewDelegate代理方法 -
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    NSInteger num = [self numberOfCell];
    NSInteger index = self.scrollView.contentOffset.x / CGRectGetWidth(self.frame);
    if (index == 0) {
        self.scrollView.contentOffset = CGPointMake(5 * CGRectGetWidth(self.frame), 0);
    }else if (index == (num + 1)) {
        self.scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.frame), 0);
    }
    self.pageControl.currentPage = index - 1;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    [self.timer invalidate];
    self.timer = nil;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:[self timeInterval] target:self selector:@selector(timeAction) userInfo:nil repeats:YES];
}
#pragma mark - 從CarouselFigureViewDataSource代理中獲取數(shù)據(jù) -
- (NSInteger)numberOfCell{
    if (self.dataSource && [self.dataSource respondsToSelector:@selector(numberOfCellInCarouselFigureView:)]) {
        return [self.dataSource numberOfCellInCarouselFigureView:self];
    }else {
        return 0;
    }
}
- (UIView *)cellViewForIndex:(NSInteger)index{
    if (self.dataSource && [self.dataSource carouselFigureView:self cellForIndex:index]) {
        return [self.dataSource carouselFigureView:self cellForIndex:index];
    }else {
        return nil;
    }
}
- (NSTimeInterval)timeInterval{
    if (self.dataSource && [self.dataSource respondsToSelector:@selector(timeIntervalForScrollInCarouselFigureView:)]) {
        return [self.dataSource timeIntervalForScrollInCarouselFigureView:self];
    }else {
        return KTimeInterval;
    }
}
- (CarouselFigureViewDirection)direction{
    if (self.dataSource && [self.dataSource respondsToSelector:@selector(directionForScrollInCarouselFigureView:)]) {
        return [self.dataSource directionForScrollInCarouselFigureView:self];
    }else {
        return CarouselFigureViewDirection_Right;
    }
}
- (void)dealloc{
    self.timer = nil;
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末舷暮,一起剝皮案震驚了整個(gè)濱河市瓢谢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖待锈,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡留美,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門伸刃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谎砾,“玉大人,你說(shuō)我怎么就攤上這事捧颅【巴迹” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵碉哑,是天一觀的道長(zhǎng)挚币。 經(jīng)常有香客問我,道長(zhǎng)扣典,這世上最難降的妖魔是什么妆毕? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮贮尖,結(jié)果婚禮上笛粘,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好薪前,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布润努。 她就那樣靜靜地躺著,像睡著了一般序六。 火紅的嫁衣襯著肌膚如雪任连。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天例诀,我揣著相機(jī)與錄音随抠,去河邊找鬼。 笑死繁涂,一個(gè)胖子當(dāng)著我的面吹牛拱她,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扔罪,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼秉沼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了矿酵?” 一聲冷哼從身側(cè)響起唬复,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎全肮,沒想到半個(gè)月后敞咧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辜腺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年休建,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片评疗。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡测砂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出百匆,到底是詐尸還是另有隱情砌些,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布加匈,位于F島的核電站寄症,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矩动。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一释漆、第九天 我趴在偏房一處隱蔽的房頂上張望悲没。 院中可真熱鬧,春花似錦、人聲如沸示姿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)栈戳。三九已至岂傲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間子檀,已是汗流浹背镊掖。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留褂痰,地道東北人亩进。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像缩歪,于是被迫代替她去往敵國(guó)和親归薛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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