| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- //
- // JXBannerView.m
- // AICity
- //
- // Banner 轮播组件实现
- //
- #import "JXBannerView.h"
- #import <SDWebImage/SDWebImage.h>
- #import <Masonry/Masonry.h>
- 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 () <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
- @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<JXBannerItem *> *)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
|