这是利用人的视觉错觉来实现无限轮播,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 = ;
layout.minimumInteritemSpacing = ;
//设置滚动方向
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 = ; //添加标题和分页
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 > )
{
[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 > )
{
[_carouselImages insertObject:[self.imgs lastObject] atIndex:];
[_carouselImages addObject:self.imgs[]];
}
}
return _carouselImages;
} #pragma mark 自动滚动
- (void)startScrollAutomtically
{
NSInteger currentIndex = self.currentIndex + ;
currentIndex = (currentIndex == self.carouselImages.count) ? : currentIndex; NSIndexPath *indexPath = [NSIndexPath indexPathForItem:currentIndex inSection:];
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 == )
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem: inSection:];
[self.carouselView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
self.currentIndex = ;
}
} #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 + )
{
self.currentIndex = ;
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.currentIndex inSection:];
[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:];
[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 > )
{
[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 + )
{
// NSLog(@"%zd",currentIndex);
NSInteger index = _currentIndex > ? _currentIndex - : ;
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 = ;
self.currentPage = ;
}
return self;
} + (instancetype)pageControlViewWithFrame:(CGRect)frame
{
return [self pageControlViewWithFrame:frame dotsSize:CGSizeZero dotsMargin:];
} + (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 = ;
CGFloat dotViewMargin = ;
CGFloat dotViewY = ;
CGFloat dotViewH = ;
CGFloat dotViewMarginLeft = ; dotViewW = self.dotsSize.width > ? self.dotsSize.width : ADPageControlViewDotViewDefaultWH;
dotViewH = self.dotsSize.height > ? self.dotsSize.height : ADPageControlViewDotViewDefaultWH;
dotViewMargin = self.dotsMargin > ? self.dotsMargin : (self.bounds.size.width - self.numberOfPages * dotViewW) / (self.numberOfPages - );
dotViewY = (self.bounds.size.height - dotViewH) * 0.5;
dotViewMarginLeft = (self.bounds.size.width - self.numberOfPages * dotViewW - (self.numberOfPages - ) * 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 > ? 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 = ; 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

第四十六篇、UICollectionView广告轮播控件的更多相关文章

  1. Qt编写自定义控件24-图片轮播控件

    一.前言 上一篇文章写的广告轮播控件,采用的传统widget堆积设置样式表做的,这次必须要用到更高级的QPainter来绘制了,这个才是最高效的办法,本控件参考雨田哥的轮播控件,经过大规模的改造而成, ...

  2. Qt编写自定义控件23-广告轮播控件

    一.前言 广告轮播这个控件做的比较早,是很早以前定制一个电信客户端时候用到的,该客户端需要在首页展示轮播预先设定好的图片,图片的路径可以自由设定,然后轮播的间隔速度可以自由控制,同时该控件还需要提供两 ...

  3. Android之仿京东淘宝的自动无限轮播控件

    在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程. 一.自定义控件属性 新建自定义控件SliderLayout继承于Re ...

  4. Android-----------广告图片轮播控件

    Banner广告图片轮播控件,支持无限循环和多种主题,可以灵活设置轮播样式.动画.轮播和切换时间.位置.图片加载框架等! 很多Android APP中都有广告栏,我也用过很多次了,特来写一篇博文. 先 ...

  5. Android高仿京东淘宝自动无限循环轮播控件的实现思路和过程

    在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的实现思路和过程. 一.自定义控件属性 新建自定义控件SliderLayout继承于 ...

  6. Android图片轮播控件

    Android广告图片轮播控件,支持无限循环和多种主题,可以灵活设置轮播样式.动画.轮播和切换时间.位置.图片加载框架等! 使用步骤 Step 1.依赖banner Gradle dependenci ...

  7. Android 开发最牛的图片轮播控件,基本什么都包含了。

    Android图片轮播控件  源码下载地址: Android 图片轮播 现在的绝大数app都有banner界面,实现循环播放多个广告图片和手动滑动循环等功能.因为ViewPager并不支持循环翻页, ...

  8. jquery轮播控件

    网上找了一个轮播控件,效果不错,而且很容易改,需要的同学去下载咯 地址是:http://download.csdn.net/detail/jine515073/7704143

  9. 一起写一个Android图片轮播控件

    注:本文提到的Android轮播控件Demo地址: Android图片轮播控件 1. 轮播控件的组成部分 我们以知乎日报Android客户端的轮播控件为例,分析一下轮播控件的主要组成: 首先我们要有用 ...

随机推荐

  1. cardsui-for-android

    https://github.com/Androguide/cardsui-for-android cardsui-for-android-master.zip

  2. iOS修改声明为readonly的属性值

    本文讨论的是,对于类中声明为 readonly 的属性值,我们就不可以修改其值了么?如何可以,那么如何修改呢? 为了便于说明,定义一个 ACLStudent 的类: ACLStudent.h @int ...

  3. LVS 之 DR 2

    http://www.cnblogs.com/kgdxpr/archive/2013/09/09/3309776.html http://lyp0909.blog.51cto.com/508999/5 ...

  4. DDNS 的工作原理及其在 Linux 上的实现--转

    http://www.ibm.com/developerworks/cn/linux/1305_wanghz_ddns/index.html DDNS (Dynamic DNS) 扩展了 DNS 将客 ...

  5. c实例_挑战程序竞赛,蚂蚁

    #include <stdio.h> //蚂蚁的题目 int max(int a,int b) { int count; count=a>b?a:b; return count; } ...

  6. IIS 之 添加绑定域名 或 设置输入IP直接访问网站

    1.打开IIS,右键站点 → 编辑绑定,弹出“网站绑定”窗口,如下图:   2.点击“添加”,弹出“添加网站绑定”窗口,如下图:   注意:若想输入 IP 地址直接访问,则可以有以下两种设置任一均可: ...

  7. X-Sequence

    Description Let {xi} be the infinite sequence of integers: 1) x0 = A; 2) xi = (alpha * xi-1^2 + beta ...

  8. Node.js module.exports和exports的区别

    require 用来加载代码,而 exports 和 module.exports 则用来导出代码,从接触node.js就不会它们两陌生,上代码: foo.js exports.a = functio ...

  9. “Request Entity Too Large” 上传图片出现大小限制

    昨天公司安卓app上传了图片爆了下面这个错误 <"-//IETF//DTD HTML 2.0//EN"> <html><head> <ti ...

  10. HDU 2295 Radar (DLX + 二分)

    Radar Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...