先看看效果.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