zoukankan      html  css  js  c++  java
  • 第四十六篇、UICollectionView广告轮播控件

    这是利用人的视觉错觉来实现无限轮播,UICollectionView 有很好的重用机制,这只是部分核心代码,后期还要继续完善和代码重构。

    #import <UIKit/UIKit.h>
    #import "ADPageControlView.h"
    
    @interface ADCarouselView : UIView
    
    /**图片资源数组*/
    @property (nonatomic, strong) NSArray *imgs;
    
    /**标题数组*/
    @property (nonatomic, strong) NSArray *titles;
    
    /**是否无限循环轮播*/
    @property (nonatomic, assign)  BOOL loop;
    
    /**自动轮播时间间隔,默认为0,0表示不开启自动轮播*/
    @property (nonatomic, assign)  NSTimeInterval automaticallyScrollDuration;
    
    /**图片的展开方式*/
    @property (nonatomic, assign)  UIViewContentMode imageContentMode;
    
    /**占位图片*/
    @property (copy, nonatomic) NSString *placeholderImageName;
    
    + (instancetype)carouselViewWithFrame:(CGRect)frame;
    
    /**分页控制(相关属性自行设置,不设置使用默认属性)*/
    @property (strong, nonatomic) ADPageControlView *pageControlView;
    /**标题*/
    @property (nonatomic, strong) UILabel *titleLabel;
    
    @end
    #import "ADCarouselView.h"
    
    #define kADCarouselViewLeftMargin 10
    
    #define kPageControlViewDefaultW 80
    #define kPageControlViewDefaultH 44
    
    #define kTitleLabelToTitleLabelMargin 10
    
    #define kTitleLabelDefaultH kPageControlViewDefaultH
    
    #define kPageControlViewDefaultFrame CGRectMake([UIScreen mainScreen].bounds.size.width - kPageControlViewDefaultW - kADCarouselViewLeftMargin, self.bounds.size.height - kPageControlViewDefaultH, kPageControlViewDefaultW, kPageControlViewDefaultH)
    
    #define kTitleLabelDefaultFrame CGRectMake(kADCarouselViewLeftMargin, self.bounds.size.height - kTitleLabelDefaultH, [UIScreen mainScreen].bounds.size.width - kPageControlViewDefaultW - kADCarouselViewLeftMargin - kADCarouselViewLeftMargin - kTitleLabelToTitleLabelMargin, kTitleLabelDefaultH)
    
    #define kTitleLabelDefaultTextColor [UIColor whiteColor]
    #define kTitleLabelDefaultFont [UIFont systemFontOfSize:14]
    
    @class ADCarouselViewCell;
    
    #pragma mark - ADCarouselViewCell(轮播图子控件)
    
    @interface ADCarouselViewCell : UICollectionViewCell
    
    /**图片名称*/
    @property (copy, nonatomic) NSString *imgName;
    
    @end
    
    @interface ADCarouselViewCell()
    
    /**图片*/
    @property (weak, nonatomic) UIImageView *imgView;
    
    @end
    
    @implementation ADCarouselViewCell
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self setUpCarouselViewCell];
        }
        return self;
    }
    
    - (void)setUpCarouselViewCell
    {
        UIImageView *imgView = [[UIImageView alloc] init];
        imgView.contentMode = UIViewContentModeCenter;
        self.imgView = imgView;
        [self.contentView addSubview:self.imgView];
        self.backgroundColor = [UIColor whiteColor];
    }
    
    - (void)setImgName:(NSString *)imgName
    {
        _imgName = imgName;
        self.imgView.image = [UIImage imageNamed:_imgName];
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        self.imgView.frame = self.bounds;
    }
    
    @end
    
    #pragma mark - ADCarouselView(轮播图控件)
    
    @interface ADCarouselView()<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>
    
    /**轮播控件*/
    @property (weak, nonatomic) UICollectionView *carouselView;
    
    /**布局*/
    @property (nonatomic, strong) UICollectionViewFlowLayout *layout;
    
    /**轮播图片数组*/
    @property (nonatomic, strong) NSMutableArray *carouselImages;
    
    /**自动轮播定时器*/
    @property (nonatomic, strong) NSTimer *timer;
    
    /**当前滚动的位置*/
    @property (nonatomic, assign)  NSInteger currentIndex;
    
    /**上次滚动的位置*/
    @property (nonatomic, assign)  NSInteger lastIndex;
    
    @end
    
    @implementation ADCarouselView
    
    + (instancetype)carouselViewWithFrame:(CGRect)frame
    {
        ADCarouselView *carouselView = [[self alloc] initWithFrame:frame];
        return carouselView;
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame])
        {
            //1、添加collectionview
            //1.1设置collectionview布局
            UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
            self.layout = layout;
            layout.minimumLineSpacing = 0;
            layout.minimumInteritemSpacing = 0;
            //设置滚动方向
            layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
            //1.2初始化collectionview
            UICollectionView *carouselView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
            carouselView.showsHorizontalScrollIndicator = NO;
            carouselView.pagingEnabled = YES;
            carouselView.delegate = self;
            carouselView.dataSource = self;
            //2、注册cell类型
            [carouselView registerClass:[ADCarouselViewCell class] forCellWithReuseIdentifier:@"carouselViewCell"];
            self.carouselView = carouselView;
            //3、添加为子控件
            [self addSubview:carouselView];
            //4、设置自动滚动时间间隔
            self.loop = NO;
            self.automaticallyScrollDuration = 0;
            
            //添加标题和分页
            self.titleLabel.frame = kTitleLabelDefaultFrame;
            self.pageControlView.frame = kPageControlViewDefaultFrame;
            self.titleLabel.textColor = kTitleLabelDefaultTextColor;
            self.titleLabel.font = kTitleLabelDefaultFont;
        }
        return self;
    }
    
    #pragma mark 自动滚动时间设置
    
    - (void)setAutomaticallyScrollDuration:(NSTimeInterval)automaticallyScrollDuration
    {
        _automaticallyScrollDuration = automaticallyScrollDuration;
        if (_automaticallyScrollDuration > 0)
        {
            [self.timer invalidate];
            self.timer = nil;
            NSTimer *timer = [NSTimer timerWithTimeInterval:self.automaticallyScrollDuration target:self selector:@selector(startScrollAutomtically) userInfo:nil repeats:YES];
            [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
            self.timer = timer;
        }
        else
        {
            [self.timer invalidate];
        }
    }
    
    #pragma mark 构造新的图片数组
    
    - (NSMutableArray *)carouselImages
    {
        if (!_carouselImages) {
            _carouselImages = [NSMutableArray arrayWithArray:self.imgs];
            if (self.loop && self.imgs.count > 0)
            {
                [_carouselImages insertObject:[self.imgs lastObject] atIndex:0];
                [_carouselImages addObject:self.imgs[0]];
            }
        }
        return _carouselImages;
    }
    
    #pragma mark 自动滚动
    - (void)startScrollAutomtically
    {
        NSInteger currentIndex = self.currentIndex + 1;
        currentIndex = (currentIndex == self.carouselImages.count) ? 1 : currentIndex;
        
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:currentIndex inSection:0];
        BOOL isNeedAnim = self.automaticallyScrollDuration <= 0.3 ? NO : YES;
        [self.carouselView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:isNeedAnim];
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        self.carouselView.frame = self.bounds;
        
        //默认滚动到第一张图片
        if (self.loop && self.carouselView.contentOffset.x == 0)
        {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:1 inSection:0];
            [self.carouselView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
            self.currentIndex = 1;
        }
    }
    
    #pragma mark 代理方法
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        ADCarouselViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"carouselViewCell" forIndexPath:indexPath];
        cell.imgView.contentMode = self.imageContentMode;
        cell.imgName = self.carouselImages[indexPath.row];
        return cell;
    }
    
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        return self.carouselImages.count;
    }
    
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        CGFloat width = self.frame.size.width;
        NSInteger index = (scrollView.contentOffset.x + width * 0.5) / width;
        if (self.loop)
        {
            //当滚动到最后一张图片时,继续滚向后动跳到第一张
            if (index == self.imgs.count + 1)
            {
                self.currentIndex = 1;
                NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.currentIndex inSection:0];
                [self.carouselView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
                return;
            }
            
            //当滚动到第一张图片时,继续向前滚动跳到最后一张
            if (scrollView.contentOffset.x < width * 0.5)
            {
                self.currentIndex = self.imgs.count;
                NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.currentIndex inSection:0];
                [self.carouselView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
                return;
            }
        }
        
        //避免多次调用currentIndex的setter方法
        if (self.currentIndex != self.lastIndex)
        {
            self.currentIndex = index;
        }
        self.lastIndex = index;
        
    }
    
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    {
        //关闭自动滚动
        [self.timer invalidate];
    }
    
    - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
    {
        if (self.automaticallyScrollDuration > 0)
        {        
            [self.timer invalidate];
            self.timer = nil;
            NSTimer *timer = [NSTimer timerWithTimeInterval:self.automaticallyScrollDuration target:self selector:@selector(startScrollAutomtically) userInfo:nil repeats:YES];
            [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
            self.timer = timer;
        }
    }
    
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        return self.frame.size;
    }
    
    - (void)setCurrentIndex:(NSInteger)currentIndex
    {
        _currentIndex = currentIndex;
        
        if (_currentIndex < self.imgs.count + 1)
        {
    //        NSLog(@"%zd",currentIndex);
            NSInteger index = _currentIndex > 0 ? _currentIndex - 1 : 0;
            self.pageControlView.currentPage = index;
            
            self.titleLabel.hidden = !self.titles.count;
            if (self.titles.count > index)
            {
                self.titleLabel.text = self.titles[index];
            }
            
            return;
        }
        
    }
    
    - (void)setImgs:(NSArray *)imgs
    {
        _imgs = imgs;
        
        self.pageControlView.hidden = !_imgs.count;
        self.pageControlView.numberOfPages = _imgs.count;
    }
    
    - (ADPageControlView *)pageControlView
    {
        if (!_pageControlView) {
            _pageControlView = [ADPageControlView pageControlViewWithFrame:CGRectZero];
            [self addSubview:_pageControlView];
        }
        return _pageControlView;
    }
    
    - (UILabel *)titleLabel
    {
        if (!_titleLabel)
        {
            _titleLabel = [[UILabel alloc] init];
            [self addSubview:_titleLabel];
        }
        return _titleLabel;
    }
    
    
    @end

    PageControl控件:

    #import <UIKit/UIKit.h>
    
    @interface ADPageControlView : UIView
    
    /**总页数*/
    @property(assign,nonatomic) NSInteger numberOfPages;
    /**当前页*/
    @property(assign,nonatomic) NSInteger currentPage;
    
    /**所有分页dot的背景*/
    @property (nonatomic, strong) UIImage *allPageDotImage;
    /**当前dot的背景*/
    @property (nonatomic, strong) UIImage *currentPageDotImage;
    
    /**所有分页dot的背景颜色*/
    @property (nonatomic, strong) UIColor *allPageDotBackgroundColor;
    /**当前dot的背景颜色*/
    @property (nonatomic, strong) UIColor *currentPageDotColor;
    
    /**dot的圆角,默认是dot点高的一半*/
    @property (nonatomic, assign)  CGFloat dotCorner;
    
    + (instancetype)pageControlViewWithFrame:(CGRect)frame;
    /**
     dotsSize:点的大小
     dotsMargin:点之间的间距
     */
    + (instancetype)pageControlViewWithFrame:(CGRect)frame dotsSize:(CGSize)dotsSize dotsMargin:(CGFloat)dotsMargin;
    @end
    #import "ADPageControlView.h"
    
    #define ADPageControlViewDotViewDefaultWH 10
    #define ADPageControlViewDotViewDefaultColor [UIColor grayColor]
    #define ADPageControlViewCurrentDotViewColor [UIColor whiteColor]
    
    
    @interface ADPageControlView()
    
    /**小圆点*/
    @property (nonatomic, strong) NSMutableArray *dots;
    /**小圆点大小*/
    @property (nonatomic, assign)  CGSize dotsSize;
    /**小圆点之间的间距*/
    @property (nonatomic, assign)  CGFloat dotsMargin;
    /**是否完全自定义*/
    @property (nonatomic, assign)  BOOL is_custom;
    
    @end
    
    @implementation ADPageControlView
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame])
        {
            self.numberOfPages = 0;
            self.currentPage = 0;
        }
        return self;
    }
    
    + (instancetype)pageControlViewWithFrame:(CGRect)frame
    {
        return [self pageControlViewWithFrame:frame dotsSize:CGSizeZero dotsMargin:0];
    }
    
    + (instancetype)pageControlViewWithFrame:(CGRect)frame dotsSize:(CGSize)dotsSize dotsMargin:(CGFloat)dotsMargin
    {
        ADPageControlView *pageControlView = [[ADPageControlView alloc] initWithFrame:frame];
        pageControlView.dotsSize = dotsSize;
        pageControlView.dotsMargin = dotsMargin;
        pageControlView.is_custom = YES;
        return pageControlView;
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        CGFloat dotViewW = 0;
        CGFloat dotViewMargin = 0;
        CGFloat dotViewY = 0;
        CGFloat dotViewH = 0;
        CGFloat dotViewMarginLeft = 0;
        
        dotViewW = self.dotsSize.width > 0 ? self.dotsSize.width : ADPageControlViewDotViewDefaultWH;
        dotViewH = self.dotsSize.height > 0 ? self.dotsSize.height : ADPageControlViewDotViewDefaultWH;
        dotViewMargin = self.dotsMargin > 0 ? self.dotsMargin : (self.bounds.size.width - self.numberOfPages * dotViewW) / (self.numberOfPages - 1);
        dotViewY = (self.bounds.size.height - dotViewH) * 0.5;
        dotViewMarginLeft = (self.bounds.size.width - self.numberOfPages * dotViewW - (self.numberOfPages - 1) * dotViewMargin) * 0.5;
        
        [self.dots enumerateObjectsUsingBlock:^(UIImageView *dotView, NSUInteger idx, BOOL * _Nonnull stop) {
            CGFloat dotViewX = dotViewMarginLeft + idx * (dotViewW + dotViewMargin);
            dotView.frame = CGRectMake(dotViewX, dotViewY, dotViewW, dotViewH);
            
            CGFloat cornerRadius = self.dotCorner > 0 ? self.dotCorner : dotViewH * 0.5;
            dotView.layer.cornerRadius = cornerRadius;
        }];
    }
    
    - (void)setNumberOfPages:(NSInteger)numberOfPages
    {
        _numberOfPages = numberOfPages;
        
        [self.dots enumerateObjectsUsingBlock:^(UIView *dotView, NSUInteger idx, BOOL * _Nonnull stop) {
            [dotView removeFromSuperview];
        }];
        
        [self.dots removeAllObjects];
        
        for (NSInteger i = 0; i < _numberOfPages; i++)
        {
            UIImageView *dotView = [[UIImageView alloc] init];
            
            dotView.backgroundColor = self.allPageDotBackgroundColor ? self.allPageDotBackgroundColor : ADPageControlViewDotViewDefaultColor;
            
            dotView.image = self.allPageDotImage;
            [self.dots addObject:dotView];
            
            [self addSubview:dotView];
        }
    }
    
    - (void)setCurrentPage:(NSInteger)currentPage
    {
        _currentPage = currentPage;
        [self.dots enumerateObjectsUsingBlock:^(UIImageView *dotView, NSUInteger idx, BOOL * _Nonnull stop)
        {
            dotView.backgroundColor = self.allPageDotBackgroundColor ? self.allPageDotBackgroundColor : ADPageControlViewDotViewDefaultColor;
            dotView.image = self.allPageDotImage;
            if (idx == _currentPage)
            {
                dotView.backgroundColor = ADPageControlViewCurrentDotViewColor;
                dotView.image = self.currentPageDotImage;
                
            }
        }];
    }
    
    - (NSMutableArray *)dots
    {
        if (!_dots) {
            _dots = [NSMutableArray array];
        }
        return _dots;
    }
    
    @end
  • 相关阅读:
    【转载】JS中bind方法与函数柯里化
    计算机中位(bit), 字节(byte), 字(word)的关系
    MySQL 正则(Regular Expression) 邮箱(Email)
    eclipse remote system explorer operation
    Hibernate save, saveOrUpdate, persist, merge, update 区别
    产品经理 写SQL
    DevOps Scrum Agile Tech Debt
    SpringMVC 集成 jackson,日志格式报错:org.codehaus.jackson.map.JsonMappingException: Can not construct instance of java.util.Date from String value
    EDAS Serverless & Kubernetes SLB LVS Nginx
    阿里巴巴 开发者 工具 开源 社区
  • 原文地址:https://www.cnblogs.com/HJQ2016/p/5929624.html
Copyright © 2011-2022 走看看