iOS 輪播圖

weixin_33850890發表於2016-12-08
2167733-9f3b7d2a9e2240cb.gif
先看看效果.gif
#import <UIKit/UIKit.h>
@class CarouselFigureView;
typedef NS_ENUM(NSInteger,CarouselFigureViewDirection) {
    CarouselFigureViewDirection_Left,    // 向左
    CarouselFigureViewDirection_Right    // 向右
};
@protocol CarouselFigureViewDataSource <NSObject>
@required
/*
 * 功能:返回顯示cell的個數
 * 引數carouselFigureView:當前滾動檢視
 * 返回:返回滾動檢視cell的個數
 */
- (NSInteger)numberOfCellInCarouselFigureView:(UIView *)carouselFigureView;
/*
 * 功能:返回每個cell的內容
 * 引數carouselFigureView:當前滾動檢視
 * 引數index:每個滾動cell的下標
 * 返回:返回每個cell上的檢視
 */
- (UIView *)carouselFigureView:(UIView *)carouselFigureView cellForIndex:(NSInteger)index;
@optional
/*
 * 功能:返回定時滾動的時間,預設是3秒
 * 引數carouselFigureView:當前滾動檢視
 * 返回:返回每次滾動的時間間隔
 */
- (NSTimeInterval)timeIntervalForScrollInCarouselFigureView:(UIView *)carouselFigureView;
/*
 * 功能:返回滾動方向,預設是向右
 * 引數carouselFigureView:當前滾動檢視
 * 返回:返回滾動檢視的方向
 */
- (CarouselFigureViewDirection)directionForScrollInCarouselFigureView:(UIView *)carouselFigureView;
/*
 * 功能:設定下標檢視樣式
 * 引數carouselFigureView:當前滾動檢視
 * 引數pageControl:滾動下標(可以在此修改滾動下標的樣式)
 */
- (void)carouselFigureView:(UIView *)carouselFigureView pageControl:(UIPageControl *)pageControl;
@end
@protocol CarouselFigureViewDelegate <NSObject>
@optional
/*
 * 功能:當點選某個cell時,觸發的方法回撥
 * 引數carouselFigureView:當前滾動檢視
 * 引數index:點選cell的下標
 */
- (void)carouselFigureView:(UIView *)carouselFigureView didSelectCell:(NSInteger)index;
@end
@interface CarouselFigureView :UIView
/*
 * 功能:資料來源代理
 */
@property (nonatomic,assign)id<CarouselFigureViewDataSource> dataSource;
/*
 * 功能:響應事件代理
 */
@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);
        // 新增滾動檢視
        [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];
}
// 新增輕拍手勢
- (void)addGesture{
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognizerAction:)];
    [self addGestureRecognizer:gesture];
}
// 輕拍手勢觸發函式
- (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代理中獲取資料 -
- (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

相關文章