#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