You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
905 lines
33 KiB
905 lines
33 KiB
// |
|
// YJBannerView.m |
|
// YJBannerViewDemo |
|
// |
|
// Created by YJHou on 2015/5/24. |
|
// Copyright © 2015年 Address:https://github.com/stackhou/YJBannerViewOC . All rights reserved. |
|
// |
|
|
|
/** |
|
__ __ _ ____ __ ___ |
|
\ \ / / | | __ ) __ _ _ __ _ __ ___ _ __ \ / (_) _____ __ |
|
\ V / | | _ \ / _` | '_ \| '_ \ / _ \ '__\ \ / /| |/ _ \ \ /\ / / |
|
| | |_| | |_) | (_| | | | | | | | __/ | \ V / | | __/\ V V / |
|
|_|\___/|____/ \__,_|_| |_|_| |_|\___|_| \_/ |_|\___| \_/\_/ |
|
|
|
*/ |
|
|
|
#import "YJBannerView.h" |
|
#import "YJBannerViewCell.h" |
|
#import "UIView+YJBannerViewExt.h" |
|
#import "YJHollowPageControl.h" |
|
#import "YJBannerViewFooter.h" |
|
|
|
static NSString *const bannerViewCellId = @"YJBannerView"; |
|
static NSString *const bannerViewFooterId = @"YJBannerViewFooter"; |
|
static NSInteger const totalCollectionViewCellCount = 200; |
|
#define kPageControlDotDefaultSize CGSizeMake(8, 8) |
|
#define BANNER_FOOTER_HEIGHT 49.0 |
|
|
|
@interface YJBannerView () <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout> { |
|
YJBannerViewCollectionView *_collectionView; |
|
UICollectionViewFlowLayout *_flowLayout; |
|
} |
|
|
|
@property (nonatomic, weak) UIControl *pageControl; |
|
@property (nonatomic, weak) NSTimer *timer; |
|
@property (nonatomic, assign) NSInteger totalBannerItemsCount; |
|
@property (nonatomic, strong) NSArray *saveScrollViewGestures; |
|
@property (nonatomic, strong) YJBannerViewFooter *bannerFooter; |
|
@property (nonatomic, strong) NSArray *showNewDatasource; |
|
@property (nonatomic, assign) CGFloat lastContentOffset; |
|
|
|
@end |
|
|
|
@implementation YJBannerView |
|
@synthesize autoScroll = _autoScroll; |
|
@synthesize cycleScrollEnable = _cycleScrollEnable; |
|
@synthesize bannerImageViewContentMode = _bannerImageViewContentMode; |
|
@synthesize pageControlNormalColor = _pageControlNormalColor; |
|
@synthesize pageControlHighlightColor = _pageControlHighlightColor; |
|
|
|
#pragma mark - Public API |
|
+ (YJBannerView *)bannerViewWithFrame:(CGRect)frame |
|
dataSource:(id<YJBannerViewDataSource>)dataSource |
|
delegate:(id<YJBannerViewDelegate>)delegate |
|
emptyImage:(UIImage *)emptyImage |
|
placeholderImage:(UIImage *)placeholderImage |
|
selectorString:(NSString *)selectorString{ |
|
|
|
YJBannerView *bannerView = [[YJBannerView alloc] initWithFrame:frame]; |
|
bannerView.dataSource = dataSource; |
|
bannerView.delegate = delegate; |
|
bannerView.bannerViewSelectorString = selectorString; |
|
bannerView.emptyImage = emptyImage; |
|
bannerView.placeholderImage = placeholderImage; |
|
|
|
return bannerView; |
|
} |
|
|
|
- (void)reloadData{ |
|
|
|
[self invalidateTimer]; |
|
self.showNewDatasource = [self _getImageDataSources]; |
|
|
|
// Hidden when data source is greater than zero |
|
self.backgroundImageView.hidden = ([self _imageDataSources].count > 0); |
|
|
|
if ([self _imageDataSources].count > 1) { |
|
self.collectionView.scrollEnabled = YES; |
|
[self setAutoScroll:self.autoScroll]; |
|
} else { |
|
|
|
if ([self _imageDataSources].count == 0) { self.showFooter = NO; } |
|
|
|
BOOL isCan = ([self _imageDataSources].count == 0)?NO:(self.showFooter?YES:NO); |
|
|
|
self.collectionView.scrollEnabled = isCan; |
|
|
|
[self invalidateTimerWhenAutoScroll]; |
|
} |
|
|
|
[self _setFooterViewCanShow:self.showFooter]; |
|
[self _setupPageControl]; |
|
|
|
// Regist Custom Cell |
|
if (self.dataSource && [self.dataSource respondsToSelector:@selector(bannerViewRegistCustomCellClass:)] && [self.dataSource bannerViewRegistCustomCellClass:self]) { |
|
NSArray *clazzs = [self.dataSource bannerViewRegistCustomCellClass:self]; |
|
for (Class clazz in clazzs) { |
|
[self.collectionView registerClass:clazz forCellWithReuseIdentifier:NSStringFromClass(clazz)]; |
|
} |
|
} |
|
|
|
[self.collectionView reloadData]; |
|
} |
|
|
|
- (instancetype)initWithFrame:(CGRect)frame{ |
|
self = [super initWithFrame:frame]; |
|
if (self) { |
|
[self _initSetting]; |
|
[self addSubview:self.collectionView]; |
|
} |
|
return self; |
|
} |
|
|
|
- (id)initWithCoder:(NSCoder *)aDecoder{ |
|
if (self = [super initWithCoder:aDecoder]) { |
|
[self _initSetting]; |
|
[self addSubview:self.collectionView]; |
|
} |
|
return self; |
|
} |
|
|
|
- (void)awakeFromNib{ |
|
[super awakeFromNib]; |
|
[self _initSetting]; |
|
[self addSubview:self.collectionView]; |
|
} |
|
|
|
/** Initialize the default settings */ |
|
- (void)_initSetting{ |
|
|
|
self.backgroundColor = [UIColor whiteColor]; |
|
_autoDuration = 3.0; |
|
_autoScroll = YES; |
|
_pageControlStyle = PageControlSystem; |
|
_pageControlAliment = PageControlAlimentCenter; |
|
_pageControlDotSize = kPageControlDotDefaultSize; |
|
_pageControlBottomMargin = 10.0f; |
|
_pageControlHorizontalEdgeMargin = 10.0f; |
|
_pageControlPadding = 5.0f; |
|
|
|
_titleHeight = 30.0f; |
|
_titleEdgeMargin = 10.0f; |
|
_titleAlignment = NSTextAlignmentLeft; |
|
_bannerGestureEnable = YES; |
|
_cycleScrollEnable = YES; |
|
|
|
_showFooter = NO; |
|
_footerIndicateImageName = @"YJBannerView.bundle/yjbanner_arrow.png"; |
|
_footerNormalTitle = TFLocalizedString(@"拖动查看详情"); |
|
_footerTriggerTitle = TFLocalizedString(@"释放查看详情"); |
|
} |
|
|
|
#pragma mark - Setter && Getter |
|
- (void)setEmptyImage:(UIImage *)emptyImage{ |
|
_emptyImage = emptyImage; |
|
if (emptyImage) { |
|
self.backgroundImageView.image = emptyImage; |
|
} |
|
} |
|
|
|
- (void)setPageControlDotSize:(CGSize)pageControlDotSize{ |
|
|
|
_pageControlDotSize = pageControlDotSize; |
|
|
|
[self _setupPageControl]; |
|
if ([self.pageControl isKindOfClass:[YJHollowPageControl class]]) { |
|
YJHollowPageControl *pageContol = (YJHollowPageControl *)_pageControl; |
|
pageContol.dotSize = pageControlDotSize; |
|
} |
|
} |
|
|
|
- (void)setPageControlStyle:(PageControlStyle)pageControlStyle{ |
|
|
|
_pageControlStyle = pageControlStyle; |
|
|
|
[self _setupPageControl]; |
|
} |
|
|
|
- (void)setPageControlNormalColor:(UIColor *)pageControlNormalColor{ |
|
|
|
_pageControlNormalColor = pageControlNormalColor; |
|
|
|
if ([self.pageControl isKindOfClass:[YJHollowPageControl class]]) { |
|
YJHollowPageControl *pageControl = (YJHollowPageControl *)_pageControl; |
|
pageControl.dotNormalColor = pageControlNormalColor; |
|
}else if ([self.pageControl isKindOfClass:[UIPageControl class]]) { |
|
UIPageControl *pageControl = (UIPageControl *)_pageControl; |
|
pageControl.pageIndicatorTintColor = pageControlNormalColor; |
|
} |
|
} |
|
|
|
- (void)setPageControlHighlightColor:(UIColor *)pageControlHighlightColor{ |
|
|
|
_pageControlHighlightColor = pageControlHighlightColor; |
|
|
|
if ([self.pageControl isKindOfClass:[YJHollowPageControl class]]) { |
|
YJHollowPageControl *pageControl = (YJHollowPageControl *)_pageControl; |
|
pageControl.dotCurrentColor = pageControlHighlightColor; |
|
} else if ([self.pageControl isKindOfClass:[UIPageControl class]]){ |
|
UIPageControl *pageControl = (UIPageControl *)_pageControl; |
|
pageControl.currentPageIndicatorTintColor = pageControlHighlightColor; |
|
} |
|
} |
|
|
|
- (void)setCustomPageControlNormalImage:(UIImage *)customPageControlNormalImage{ |
|
_customPageControlNormalImage = customPageControlNormalImage; |
|
[self setCustomPageControlDotImage:customPageControlNormalImage isCurrentPageDot:NO]; |
|
} |
|
|
|
- (void)setCustomPageControlHighlightImage:(UIImage *)customPageControlHighlightImage{ |
|
_customPageControlHighlightImage = customPageControlHighlightImage; |
|
[self setCustomPageControlDotImage:customPageControlHighlightImage isCurrentPageDot:YES]; |
|
} |
|
|
|
- (void)setCustomPageControlDotImage:(UIImage *)image isCurrentPageDot:(BOOL)isCurrentPageDot{ |
|
|
|
if (!image || !self.pageControl) return; |
|
|
|
if ([self.pageControl isKindOfClass:[YJHollowPageControl class]]) { |
|
YJHollowPageControl *pageControl = (YJHollowPageControl *)_pageControl; |
|
if (isCurrentPageDot) { |
|
pageControl.dotCurrentImage = image; |
|
} else { |
|
pageControl.dotNormalImage = image; |
|
} |
|
} |
|
} |
|
|
|
- (void)setAutoScroll:(BOOL)autoScroll{ |
|
|
|
_autoScroll = autoScroll; |
|
[self invalidateTimer]; |
|
if (autoScroll) { |
|
[self _setupTimer]; |
|
} |
|
} |
|
|
|
- (void)setBannerViewScrollDirection:(BannerViewDirection)bannerViewScrollDirection{ |
|
|
|
if (self.showFooter && bannerViewScrollDirection != BannerViewDirectionLeft) { |
|
bannerViewScrollDirection = BannerViewDirectionLeft; |
|
} |
|
|
|
_bannerViewScrollDirection = bannerViewScrollDirection; |
|
|
|
if (bannerViewScrollDirection == BannerViewDirectionLeft || bannerViewScrollDirection == BannerViewDirectionRight) { |
|
self.flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; |
|
}else if (bannerViewScrollDirection == BannerViewDirectionTop || bannerViewScrollDirection == BannerViewDirectionBottom){ |
|
self.flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; |
|
} |
|
} |
|
|
|
- (void)setAutoDuration:(CGFloat)autoDuration{ |
|
|
|
_autoDuration = autoDuration; |
|
[self setAutoScroll:self.autoScroll]; |
|
} |
|
|
|
- (void)setBannerGestureEnable:(BOOL)bannerGestureEnable{ |
|
if (_bannerGestureEnable && bannerGestureEnable) { // 不操作 |
|
}else if (!_bannerGestureEnable && bannerGestureEnable){ |
|
self.collectionView.canCancelContentTouches = YES; |
|
for (NSInteger i = 0; i < self.saveScrollViewGestures.count; i++) { |
|
UIGestureRecognizer *gesture = self.saveScrollViewGestures[i]; |
|
[self.collectionView addGestureRecognizer:gesture]; |
|
} |
|
}else if (_bannerGestureEnable && !bannerGestureEnable){ |
|
self.collectionView.canCancelContentTouches = NO; |
|
for (UIGestureRecognizer *gesture in self.collectionView.gestureRecognizers) { |
|
[self.collectionView removeGestureRecognizer:gesture]; |
|
} |
|
} |
|
_bannerGestureEnable = bannerGestureEnable; |
|
} |
|
|
|
- (void)setBannerImageViewContentMode:(UIViewContentMode)bannerImageViewContentMode{ |
|
_bannerImageViewContentMode = bannerImageViewContentMode; |
|
self.backgroundImageView.contentMode = bannerImageViewContentMode; |
|
} |
|
|
|
- (NSInteger)repeatCount{ |
|
if (_repeatCount <= 0) { |
|
return totalCollectionViewCellCount; |
|
}else{ |
|
if (_repeatCount % 2 != 0) { |
|
return _repeatCount + 1; |
|
}else{ |
|
return _repeatCount; |
|
} |
|
} |
|
} |
|
|
|
#pragma mark - Getter |
|
- (NSInteger)totalBannerItemsCount{ |
|
|
|
return self.cycleScrollEnable?(([self _imageDataSources].count > 1)?([self _imageDataSources].count * self.repeatCount):[self _imageDataSources].count):([self _imageDataSources].count); |
|
} |
|
|
|
- (BOOL)autoScroll{ |
|
if (self.showFooter) { |
|
return NO; |
|
} |
|
return _autoScroll; |
|
} |
|
|
|
- (BOOL)cycleScrollEnable{ |
|
if (self.showFooter) { |
|
return NO; |
|
} |
|
return _cycleScrollEnable; |
|
} |
|
|
|
- (UIFont *)titleFont{ |
|
if (!_titleFont) { |
|
_titleFont = kMainFont; |
|
} |
|
return _titleFont; |
|
} |
|
|
|
- (UIColor *)titleTextColor{ |
|
if (!_titleTextColor) { |
|
_titleTextColor = [UIColor whiteColor]; |
|
} |
|
return _titleTextColor; |
|
} |
|
|
|
- (UIColor *)titleBackgroundColor{ |
|
if (!_titleBackgroundColor) { |
|
_titleBackgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]; |
|
} |
|
return _titleBackgroundColor; |
|
} |
|
|
|
- (UIFont *)footerTitleFont{ |
|
if (!_footerTitleFont) { |
|
_footerTitleFont = kFont12; |
|
} |
|
return _footerTitleFont; |
|
} |
|
|
|
- (UIColor *)footerTitleColor{ |
|
if (!_footerTitleColor) { |
|
_footerTitleColor = [UIColor darkGrayColor]; |
|
} |
|
return _footerTitleColor; |
|
} |
|
|
|
- (UIViewContentMode)bannerImageViewContentMode{ |
|
if (!_bannerImageViewContentMode) { |
|
_bannerImageViewContentMode = UIViewContentModeScaleAspectFill; |
|
} |
|
return _bannerImageViewContentMode; |
|
} |
|
|
|
- (UIColor *)pageControlNormalColor{ |
|
if (!_pageControlNormalColor) { |
|
_pageControlNormalColor = [UIColor lightGrayColor]; |
|
} |
|
return _pageControlNormalColor; |
|
} |
|
|
|
- (UIColor *)pageControlHighlightColor{ |
|
if (!_pageControlHighlightColor) { |
|
_pageControlHighlightColor = [UIColor whiteColor]; |
|
} |
|
return _pageControlHighlightColor; |
|
} |
|
|
|
- (NSArray *)saveScrollViewGestures{ |
|
if (!_saveScrollViewGestures) { |
|
_saveScrollViewGestures = self.collectionView.gestureRecognizers; |
|
} |
|
return _saveScrollViewGestures; |
|
} |
|
|
|
#pragma mark - layoutSubviews |
|
- (void)layoutSubviews{ |
|
[super layoutSubviews]; |
|
|
|
self.dataSource = self.dataSource; |
|
[super layoutSubviews]; |
|
|
|
self.flowLayout.itemSize = self.frame.size; |
|
|
|
self.collectionView.frame = self.bounds; |
|
|
|
if (self.collectionView.contentOffset.x == 0 && self.totalBannerItemsCount) { |
|
NSInteger targetIndex = self.cycleScrollEnable?(self.totalBannerItemsCount * 0.5):(0); |
|
[self _scrollBannerViewToSpecifiedPositionIndex:targetIndex animated:NO]; |
|
} |
|
|
|
CGSize size = CGSizeZero; |
|
|
|
if ([self.pageControl isKindOfClass:[YJHollowPageControl class]]) { |
|
|
|
YJHollowPageControl *pageControl = (YJHollowPageControl *)_pageControl; |
|
|
|
if (!(self.customPageControlNormalImage && self.customPageControlHighlightImage && CGSizeEqualToSize(kPageControlDotDefaultSize, self.pageControlDotSize))) { |
|
pageControl.dotSize = self.pageControlDotSize; |
|
} |
|
|
|
size = [pageControl sizeForNumberOfPages:[self _imageDataSources].count]; |
|
} else { |
|
size = CGSizeMake([self _imageDataSources].count * self.pageControlDotSize.width * 1.5, self.pageControlDotSize.height); |
|
} |
|
CGFloat x = (self.width_bannerView - size.width) * 0.5; |
|
if (self.pageControlAliment == PageControlAlimentLeft) { |
|
x = 0.0f; |
|
}else if (self.pageControlAliment == PageControlAlimentCenter){ |
|
}else if (self.pageControlAliment == PageControlAlimentRight){ |
|
x = self.collectionView.width_bannerView - size.width; |
|
} |
|
|
|
CGFloat y = self.collectionView.height_bannerView - size.height; |
|
|
|
if ([self.pageControl isKindOfClass:[YJHollowPageControl class]]) { |
|
|
|
YJHollowPageControl *pageControl = (YJHollowPageControl *)_pageControl; |
|
[pageControl sizeToFit]; |
|
} |
|
|
|
CGRect pageControlFrame = CGRectMake(x, y, size.width, size.height); |
|
if (self.pageControlAliment == PageControlAlimentLeft) { |
|
pageControlFrame.origin.x += self.pageControlHorizontalEdgeMargin; |
|
}else if (self.pageControlAliment == PageControlAlimentRight){ |
|
pageControlFrame.origin.x -= self.pageControlHorizontalEdgeMargin; |
|
} |
|
pageControlFrame.origin.y -= self.pageControlBottomMargin; |
|
self.pageControl.frame = pageControlFrame; |
|
|
|
self.pageControl.hidden = self.pageControlStyle == PageControlNone; |
|
|
|
if (self.backgroundImageView) { |
|
self.backgroundImageView.frame = self.bounds; |
|
} |
|
} |
|
|
|
#pragma mark - Resolve compatibility optimization issues |
|
- (void)willMoveToSuperview:(UIView *)newSuperview{ |
|
if (!newSuperview) { |
|
[self invalidateTimer]; |
|
} |
|
} |
|
|
|
- (void)adjustBannerViewScrollToIndex:(NSInteger)index animated:(BOOL)animated{ |
|
|
|
if (self.showNewDatasource.count == 0) { return; } |
|
if (index >= 0 && index < self.showNewDatasource.count) { |
|
if (self.autoScroll) { [self invalidateTimer]; } |
|
|
|
[self _scrollToIndex:((int)(self.totalBannerItemsCount * 0.5 + index)) animated:animated]; |
|
|
|
if (self.autoScroll) { [self _setupTimer]; } |
|
} |
|
} |
|
|
|
- (void)adjustBannerViewWhenCardScreen{ |
|
|
|
long targetIndex = [self _currentPageIndex]; |
|
if (targetIndex < self.totalBannerItemsCount) { |
|
[self _scrollBannerViewToSpecifiedPositionIndex:targetIndex animated:NO]; |
|
} |
|
} |
|
|
|
#pragma mark - UICollectionViewDataSource |
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ |
|
return self.totalBannerItemsCount; |
|
} |
|
|
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ |
|
|
|
YJBannerViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:bannerViewCellId forIndexPath:indexPath]; |
|
long itemIndex = [self _getRealIndexFromCurrentCellIndex:indexPath.item]; |
|
|
|
// Custom Cell |
|
if (self.dataSource && [self.dataSource respondsToSelector:@selector(bannerViewRegistCustomCellClass:)] && [self.dataSource bannerViewRegistCustomCellClass:self] && [self.dataSource respondsToSelector:@selector(bannerView:customCell:index:)] && [self.dataSource respondsToSelector:@selector(bannerView:reuseIdentifierForIndex:)]) { |
|
|
|
NSString *reuseIdentifier = NSStringFromClass([self.dataSource bannerView:self reuseIdentifierForIndex:itemIndex]); |
|
if (reuseIdentifier.length > 0) { |
|
UICollectionViewCell *customCell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; |
|
|
|
if ([self.dataSource bannerView:self customCell:customCell index:itemIndex]) { |
|
return customCell; |
|
} |
|
} |
|
} |
|
|
|
NSString *imagePath = (itemIndex < [self _imageDataSources].count)?[self _imageDataSources][itemIndex]:nil; |
|
NSString *title = (itemIndex < [self _titlesDataSources].count)?[self _titlesDataSources][itemIndex]:nil; |
|
|
|
if (!cell.isConfigured) { |
|
cell.titleLabelBackgroundColor = self.titleBackgroundColor; |
|
cell.titleLabelHeight = self.titleHeight; |
|
cell.titleLabelEdgeMargin = self.titleEdgeMargin; |
|
cell.titleLabelTextAlignment = self.titleAlignment; |
|
cell.titleLabelTextColor = self.titleTextColor; |
|
cell.titleLabelTextFont = self.titleFont; |
|
cell.showImageViewContentMode = self.bannerImageViewContentMode; |
|
cell.clipsToBounds = YES; |
|
cell.isConfigured = YES; |
|
} |
|
|
|
[cell cellWithSelectorString:self.bannerViewSelectorString imagePath:imagePath placeholderImage:self.placeholderImage title:title]; |
|
|
|
return cell; |
|
} |
|
|
|
// Setting Footer Size |
|
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{ |
|
return CGSizeMake((self.showFooter && [self _imageDataSources].count != 0)?[self _bannerViewFooterHeight]:0.0f, self.frame.size.height); |
|
} |
|
|
|
// Footer |
|
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{ |
|
|
|
if(kind == UICollectionElementKindSectionFooter){ |
|
|
|
YJBannerViewFooter *footer = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:bannerViewFooterId forIndexPath:indexPath]; |
|
self.bannerFooter = footer; |
|
|
|
footer.IndicateImageName = self.footerIndicateImageName; |
|
footer.footerTitleFont = self.footerTitleFont; |
|
footer.footerTitleColor = self.footerTitleColor; |
|
footer.idleTitle = self.footerNormalTitle; |
|
footer.triggerTitle = self.footerTriggerTitle; |
|
|
|
footer.hidden = !(self.showFooter && [self _imageDataSources].count != 0); |
|
|
|
return footer; |
|
}else{ |
|
UICollectionReusableView *collectionHeaderView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath]; |
|
return collectionHeaderView; |
|
} |
|
} |
|
|
|
#pragma mark - UIScrollViewDelegate |
|
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ |
|
if (self.delegate && [self.delegate respondsToSelector:@selector(bannerView:didSelectItemAtIndex:)]) { |
|
[self.delegate bannerView:self didSelectItemAtIndex:[self _getRealIndexFromCurrentCellIndex:indexPath.item]]; |
|
} |
|
if (self.didSelectItemAtIndexBlock) { |
|
self.didSelectItemAtIndexBlock([self _getRealIndexFromCurrentCellIndex:indexPath.item]); |
|
} |
|
} |
|
|
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ |
|
|
|
if (![self _imageDataSources].count) return; |
|
int itemIndex = [self _currentPageIndex]; |
|
int indexOnPageControl = [self _getRealIndexFromCurrentCellIndex:itemIndex]; |
|
|
|
// 手动退拽时左右两端 |
|
if (scrollView == self.collectionView && scrollView.isDragging && self.cycleScrollEnable) { |
|
NSInteger targetIndex = self.totalBannerItemsCount * 0.5; |
|
if (itemIndex == 0) { // top |
|
[self _scrollBannerViewToSpecifiedPositionIndex:targetIndex animated:NO]; |
|
}else if (itemIndex == (self.totalBannerItemsCount - 1)){ // bottom |
|
targetIndex -= 1; |
|
[self _scrollBannerViewToSpecifiedPositionIndex:targetIndex animated:NO]; |
|
} |
|
} |
|
|
|
// pageControl |
|
if ([self.pageControl isKindOfClass:[YJHollowPageControl class]]) { |
|
YJHollowPageControl *pageControl = (YJHollowPageControl *)_pageControl; |
|
pageControl.currentPage = indexOnPageControl; |
|
} else { |
|
UIPageControl *pageControl = (UIPageControl *)_pageControl; |
|
pageControl.currentPage = indexOnPageControl; |
|
} |
|
|
|
// Footer |
|
if (self.showFooter) { |
|
static CGFloat lastOffset; |
|
CGFloat footerDisplayOffset = (self.collectionView.contentOffset.x - (self.flowLayout.itemSize.width * (self.totalBannerItemsCount - 1))); |
|
|
|
if (footerDisplayOffset > 0){ |
|
if (footerDisplayOffset > [self _bannerViewFooterHeight]) { |
|
if (lastOffset > 0) return; |
|
self.bannerFooter.state = YJBannerViewStatusTrigger; |
|
} else { |
|
if (lastOffset < 0) return; |
|
self.bannerFooter.state = YJBannerViewStatusIdle; |
|
} |
|
lastOffset = footerDisplayOffset - [self _bannerViewFooterHeight]; |
|
} |
|
} |
|
|
|
// contentOffset |
|
[self _saveInitializationContentOffsetJudgeZero:YES]; |
|
CGFloat contentOffset = 0.0f; |
|
if (self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { |
|
contentOffset = self.collectionView.contentOffset.x; |
|
} else { |
|
contentOffset = self.collectionView.contentOffset.y; |
|
} |
|
CGFloat distance = fabs(self.lastContentOffset - contentOffset); |
|
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(bannerView:didScrollCurrentIndex:contentOffset:)]) { |
|
[self.delegate bannerView:self didScrollCurrentIndex:indexOnPageControl contentOffset:distance]; |
|
} |
|
} |
|
|
|
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ |
|
[self invalidateTimerWhenAutoScroll]; |
|
} |
|
|
|
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ |
|
|
|
[self startTimerWhenAutoScroll]; |
|
|
|
if (self.showFooter) { |
|
CGFloat footerDisplayOffset = (self.collectionView.contentOffset.x - (self.flowLayout.itemSize.width * (self.totalBannerItemsCount - 1))); |
|
|
|
if (footerDisplayOffset > [self _bannerViewFooterHeight]) { |
|
if (self.delegate && [self.delegate respondsToSelector:@selector(bannerViewFooterDidEndTrigger:)]) { |
|
[self.delegate bannerViewFooterDidEndTrigger:self]; |
|
} |
|
|
|
if (self.didEndTriggerFooterBlock) { |
|
self.didEndTriggerFooterBlock(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ |
|
[self scrollViewDidEndScrollingAnimation:self.collectionView]; |
|
} |
|
|
|
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{ |
|
if (![self _imageDataSources].count) return; |
|
int itemIndex = [self _currentPageIndex]; |
|
int indexOnPageControl = [self _getRealIndexFromCurrentCellIndex:itemIndex]; |
|
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(bannerView:didScroll2Index:)]) { |
|
[self.delegate bannerView:self didScroll2Index:indexOnPageControl]; |
|
} |
|
if (self.didScroll2IndexBlock) { |
|
self.didScroll2IndexBlock(indexOnPageControl); |
|
} |
|
|
|
[self _saveInitializationContentOffsetJudgeZero:NO]; |
|
} |
|
|
|
#pragma mark - Private function method |
|
/** install PageControl */ |
|
- (void)_setupPageControl{ |
|
|
|
if (_pageControl) [_pageControl removeFromSuperview]; |
|
|
|
if ([self _imageDataSources].count == 0) {return;} |
|
|
|
if ([self _imageDataSources].count == 1) {return;} |
|
|
|
int indexOnPageControl = [self _getRealIndexFromCurrentCellIndex:[self _currentPageIndex]]; |
|
|
|
switch (self.pageControlStyle) { |
|
case PageControlNone:{ |
|
break; |
|
} |
|
case PageControlSystem:{ |
|
UIPageControl *pageControl = [[UIPageControl alloc] init]; |
|
pageControl.numberOfPages = [self _imageDataSources].count; |
|
pageControl.currentPageIndicatorTintColor = self.pageControlHighlightColor; |
|
pageControl.pageIndicatorTintColor = self.pageControlNormalColor; |
|
pageControl.userInteractionEnabled = NO; |
|
pageControl.currentPage = indexOnPageControl; |
|
[self addSubview:pageControl]; |
|
_pageControl = pageControl; |
|
break; |
|
} |
|
case PageControlHollow:{ |
|
YJHollowPageControl *pageControl = [[YJHollowPageControl alloc] init]; |
|
pageControl.numberOfPages = [self _imageDataSources].count; |
|
pageControl.dotNormalColor = self.pageControlNormalColor; |
|
pageControl.dotCurrentColor = self.pageControlHighlightColor; |
|
pageControl.userInteractionEnabled = NO; |
|
pageControl.resizeScale = 1.0; |
|
pageControl.spacing = self.pageControlPadding; |
|
pageControl.currentPage = indexOnPageControl; |
|
[self addSubview:pageControl]; |
|
_pageControl = pageControl; |
|
break; |
|
} |
|
case PageControlCustom:{ |
|
|
|
YJHollowPageControl *pageControl = [[YJHollowPageControl alloc] init]; |
|
pageControl.numberOfPages = [self _imageDataSources].count; |
|
pageControl.dotNormalColor = self.pageControlNormalColor; |
|
pageControl.dotCurrentColor = self.pageControlHighlightColor; |
|
pageControl.userInteractionEnabled = NO; |
|
pageControl.resizeScale = 1.0; |
|
pageControl.spacing = self.pageControlPadding; |
|
pageControl.currentPage = indexOnPageControl; |
|
[self addSubview:pageControl]; |
|
_pageControl = pageControl; |
|
|
|
if (self.customPageControlNormalImage) { |
|
self.customPageControlNormalImage = self.customPageControlNormalImage; |
|
} |
|
|
|
if (self.customPageControlHighlightImage) { |
|
self.customPageControlHighlightImage = self.customPageControlHighlightImage; |
|
} |
|
} |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
/** install Timer */ |
|
- (void)_setupTimer{ |
|
|
|
[self invalidateTimer]; |
|
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:self.autoDuration target:self selector:@selector(_automaticScrollAction) userInfo:nil repeats:YES]; |
|
_timer = timer; |
|
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; |
|
} |
|
|
|
/** stop timer */ |
|
- (void)invalidateTimer{ |
|
|
|
[_timer invalidate]; |
|
_timer = nil; |
|
} |
|
|
|
/** stop timer api */ |
|
- (void)invalidateTimerWhenAutoScroll{ |
|
if (self.autoScroll) { |
|
[self invalidateTimer]; |
|
} |
|
} |
|
|
|
/** restart timer api */ |
|
- (void)startTimerWhenAutoScroll{ |
|
if (self.autoScroll) { |
|
[self _setupTimer]; |
|
} |
|
} |
|
|
|
- (void)_automaticScrollAction{ |
|
|
|
if (self.totalBannerItemsCount == 0) return; |
|
int currentIndex = [self _currentPageIndex]; |
|
if (self.bannerViewScrollDirection == BannerViewDirectionLeft || self.bannerViewScrollDirection == BannerViewDirectionTop) { |
|
[self _scrollToIndex:(currentIndex + 1) animated:YES]; |
|
}else if (self.bannerViewScrollDirection == BannerViewDirectionRight || self.bannerViewScrollDirection == BannerViewDirectionBottom){ |
|
if ((currentIndex - 1) < 0) { // 小于零 |
|
currentIndex = self.cycleScrollEnable?(self.totalBannerItemsCount * 0.5):(0); |
|
[self _scrollBannerViewToSpecifiedPositionIndex:(currentIndex - 1) animated:NO]; |
|
}else{ |
|
[self _scrollToIndex:(currentIndex - 1) animated:YES]; |
|
} |
|
} |
|
} |
|
|
|
- (void)_scrollToIndex:(int)targetIndex animated:(BOOL)animated{ |
|
|
|
if (targetIndex >= self.totalBannerItemsCount) { // 超过最大 |
|
targetIndex = self.cycleScrollEnable?(self.totalBannerItemsCount * 0.5):(0); |
|
[self _scrollBannerViewToSpecifiedPositionIndex:targetIndex animated:NO]; |
|
}else{ |
|
[self _scrollBannerViewToSpecifiedPositionIndex:targetIndex animated:animated]; |
|
} |
|
} |
|
|
|
/** current page index */ |
|
- (int)_currentPageIndex{ |
|
|
|
if (self.collectionView.width_bannerView == 0 || self.collectionView.height_bannerView == 0) {return 0;} |
|
int index = 0; |
|
if (self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { |
|
index = (self.collectionView.contentOffset.x + self.flowLayout.itemSize.width * 0.5) / self.flowLayout.itemSize.width; |
|
} else { |
|
index = (self.collectionView.contentOffset.y + self.flowLayout.itemSize.height * 0.5) / self.flowLayout.itemSize.height; |
|
} |
|
return MAX(0, index); |
|
} |
|
|
|
/** current real index */ |
|
- (int)_getRealIndexFromCurrentCellIndex:(NSInteger)cellIndex{ |
|
return (int)cellIndex % [self _imageDataSources].count; |
|
} |
|
|
|
- (NSArray *)_imageDataSources{ |
|
return self.showNewDatasource; |
|
} |
|
|
|
/** Get new data from the proxy method */ |
|
- (NSArray *)_getImageDataSources{ |
|
if (self.dataSource && [self.dataSource respondsToSelector:@selector(bannerViewImages:)]) { |
|
return [self.dataSource bannerViewImages:self]; |
|
} |
|
return @[]; |
|
} |
|
|
|
/** Get new data from the proxy method */ |
|
- (NSArray *)_titlesDataSources{ |
|
if (self.dataSource && [self.dataSource respondsToSelector:@selector(bannerViewTitles:)]) { |
|
return [self.dataSource bannerViewTitles:self]; |
|
} |
|
return @[]; |
|
} |
|
|
|
/** Footer Height */ |
|
- (CGFloat)_bannerViewFooterHeight{ |
|
if (self.dataSource && [self.dataSource respondsToSelector:@selector(bannerViewFooterViewHeight:)]) { |
|
return [self.dataSource bannerViewFooterViewHeight:self]; |
|
} |
|
return BANNER_FOOTER_HEIGHT; |
|
} |
|
|
|
/** reload 时控制尾巴的显示和消失 */ |
|
- (void)_setFooterViewCanShow:(BOOL)showFooter{ |
|
|
|
if (showFooter) { |
|
self.bannerViewScrollDirection = BannerViewDirectionLeft; |
|
self.collectionView.contentInset = UIEdgeInsetsMake(0, 0, 0, -[self _bannerViewFooterHeight]); |
|
}else{ |
|
self.collectionView.contentInset = UIEdgeInsetsZero; |
|
} |
|
|
|
if (self.bannerViewScrollDirection == BannerViewDirectionLeft) { |
|
self.collectionView.alwaysBounceHorizontal = showFooter; |
|
}else { |
|
self.collectionView.accessibilityViewIsModal = showFooter; |
|
} |
|
} |
|
|
|
/** Scroll the CollectionView to the specified location */ |
|
- (void)_scrollBannerViewToSpecifiedPositionIndex:(NSInteger)targetIndex animated:(BOOL)animated{ |
|
NSInteger itemCount = [self.collectionView numberOfItemsInSection:0]; |
|
if (targetIndex < itemCount) { |
|
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex?:0 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:animated]; |
|
} |
|
} |
|
|
|
/** Save the current offset */ |
|
- (void)_saveInitializationContentOffsetJudgeZero:(BOOL)judgeZero{ |
|
|
|
if (self.collectionView.width_bannerView == 0 || self.collectionView.height_bannerView == 0) { return; } |
|
if (judgeZero) { |
|
if (self.lastContentOffset == 0) { |
|
|
|
if (self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { |
|
self.lastContentOffset = self.collectionView.contentOffset.x; |
|
} else { |
|
self.lastContentOffset = self.collectionView.contentOffset.y; |
|
} |
|
} |
|
}else{ |
|
if (self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { |
|
self.lastContentOffset = self.collectionView.contentOffset.x; |
|
} else { |
|
self.lastContentOffset = self.collectionView.contentOffset.y; |
|
} |
|
} |
|
} |
|
|
|
#pragma mark - Lazy |
|
- (UIImageView *)backgroundImageView{ |
|
if (!_backgroundImageView) { |
|
_backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; |
|
_backgroundImageView.contentMode = self.bannerImageViewContentMode; |
|
_backgroundImageView.clipsToBounds = YES; |
|
[self insertSubview:_backgroundImageView belowSubview:self.collectionView]; |
|
} |
|
return _backgroundImageView; |
|
} |
|
|
|
- (UICollectionViewFlowLayout *)flowLayout{ |
|
if (!_flowLayout) { |
|
_flowLayout = [[UICollectionViewFlowLayout alloc] init]; |
|
_flowLayout.minimumLineSpacing = 0.0f; |
|
_flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; |
|
} |
|
return _flowLayout; |
|
} |
|
|
|
- (YJBannerViewCollectionView *)collectionView{ |
|
if (!_collectionView) { |
|
_collectionView = [[YJBannerViewCollectionView alloc] initWithFrame:self.bounds collectionViewLayout:self.flowLayout]; |
|
_collectionView.pagingEnabled = YES; |
|
_collectionView.showsHorizontalScrollIndicator = NO; |
|
_collectionView.showsVerticalScrollIndicator = NO; |
|
_collectionView.backgroundColor = [UIColor clearColor]; |
|
|
|
[_collectionView registerClass:[YJBannerViewCell class] forCellWithReuseIdentifier:bannerViewCellId]; |
|
[_collectionView registerClass:[YJBannerViewFooter class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:bannerViewFooterId]; |
|
|
|
_collectionView.dataSource = self; |
|
_collectionView.delegate = self; |
|
_collectionView.scrollsToTop = NO; |
|
} |
|
return _collectionView; |
|
} |
|
|
|
- (void)dealloc { |
|
self.collectionView.delegate = nil; |
|
self.collectionView.dataSource = nil; |
|
} |
|
|
|
@end
|
|
|