// // JXBannerView.m // AICity // // Banner 轮播组件实现 // #import "JXBannerView.h" #import #import static const NSTimeInterval kAutoScrollInterval = 5.0; // 5秒自动滚动 static NSString * const kBannerCellIdentifier = @"BannerCell"; @interface JXBannerCell : UICollectionViewCell @property (nonatomic, strong) UIImageView *imageView; @property (nonatomic, strong) UILabel *titleLabel; @end @implementation JXBannerCell - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.imageView = [[UIImageView alloc] init]; self.imageView.contentMode = UIViewContentModeScaleAspectFill; self.imageView.clipsToBounds = YES; [self.contentView addSubview:self.imageView]; self.titleLabel = [[UILabel alloc] init]; self.titleLabel.textColor = [UIColor whiteColor]; self.titleLabel.font = [UIFont boldSystemFontOfSize:16]; self.titleLabel.numberOfLines = 2; self.titleLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; [self.contentView addSubview:self.titleLabel]; [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.contentView); }]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.equalTo(self.contentView); make.height.mas_equalTo(60); }]; } return self; } @end #pragma mark - Banner View @interface JXBannerView () @property (nonatomic, strong) UICollectionView *collectionView; @property (nonatomic, strong) UIPageControl *pageControl; @property (nonatomic, strong) NSTimer *autoScrollTimer; @property (nonatomic, assign) NSInteger currentIndex; @end @implementation JXBannerView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupUI]; } return self; } - (void)dealloc { [self stopAutoScroll]; } - (void)setupUI { // CollectionView Layout UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; layout.minimumLineSpacing = 0; layout.minimumInteritemSpacing = 0; // CollectionView self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; self.collectionView.delegate = self; self.collectionView.dataSource = self; self.collectionView.pagingEnabled = YES; self.collectionView.showsHorizontalScrollIndicator = NO; self.collectionView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; [self.collectionView registerClass:[JXBannerCell class] forCellWithReuseIdentifier:kBannerCellIdentifier]; [self addSubview:self.collectionView]; // PageControl self.pageControl = [[UIPageControl alloc] init]; self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor]; self.pageControl.pageIndicatorTintColor = [[UIColor whiteColor] colorWithAlphaComponent:0.5]; self.pageControl.userInteractionEnabled = NO; [self addSubview:self.pageControl]; // Layout [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self); }]; [self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self); make.bottom.equalTo(self).offset(-10); make.height.mas_equalTo(20); }]; } - (void)updateBanners:(NSArray *)banners { self.banners = banners; self.currentIndex = 0; // 更新 PageControl self.pageControl.numberOfPages = banners.count; self.pageControl.currentPage = 0; self.pageControl.hidden = (banners.count <= 1); // 刷新数据 [self.collectionView reloadData]; // 如果有多个 Banner,启动自动轮播 if (banners.count > 1) { [self startAutoScroll]; } } #pragma mark - Auto Scroll - (void)startAutoScroll { [self stopAutoScroll]; if (self.banners.count > 1) { self.autoScrollTimer = [NSTimer scheduledTimerWithTimeInterval:kAutoScrollInterval target:self selector:@selector(autoScroll) userInfo:nil repeats:YES]; } } - (void)stopAutoScroll { if (self.autoScrollTimer) { [self.autoScrollTimer invalidate]; self.autoScrollTimer = nil; } } - (void)autoScroll { if (self.banners.count == 0) { return; } NSInteger nextIndex = (self.currentIndex + 1) % self.banners.count; NSIndexPath *indexPath = [NSIndexPath indexPathForItem:nextIndex inSection:0]; [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES]; } #pragma mark - UICollectionViewDataSource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.banners.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { JXBannerCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kBannerCellIdentifier forIndexPath:indexPath]; JXBannerItem *item = self.banners[indexPath.item]; // 使用横向封面 NSString *imageUrl = item.hCoverUrl ?: item.vCoverUrl; if (imageUrl) { [cell.imageView sd_setImageWithURL:[NSURL URLWithString:imageUrl] placeholderImage:nil]; } cell.titleLabel.text = item.name; return cell; } #pragma mark - UICollectionViewDelegate - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { JXBannerItem *item = self.banners[indexPath.item]; if (self.onBannerClick) { self.onBannerClick(item); } } #pragma mark - UICollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return collectionView.bounds.size; } #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat pageWidth = scrollView.frame.size.width; NSInteger page = (NSInteger)((scrollView.contentOffset.x + pageWidth / 2) / pageWidth); if (page >= 0 && page < self.banners.count) { self.currentIndex = page; self.pageControl.currentPage = page; } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // 用户开始拖动时停止自动滚动 [self stopAutoScroll]; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { // 用户停止拖动后重新开始自动滚动 if (!decelerate) { [self startAutoScroll]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { // 减速停止后重新开始自动滚动 [self startAutoScroll]; } @end