// // 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 () { 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)dataSource delegate:(id)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