这是利用人的视觉错觉来实现无限轮播,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. 权限执行[Android开发常见问题-4] RunTime.exec()如何以root权限执行多条指令?

    每日一贴,今天的内容关键字为权限执行 RunTime.exec()这个接口可以说是给我们开发者供给了一个很好的直观操纵底层操纵系统的机遇,但是这个接口的使用还有很多需要注意的问题.由于要完全的分析这个 ...

  2. JavaScrip基础讲座 - 神奇的ProtoType

    1. 什么是 prototype  prototype 对于 JavaScript 的 意义重大,prototype 不仅仅是一种管理对象继承的机制,更是一种出色的设计思想 在现实生活中,我们常常说, ...

  3. android圆角View实现及不同版本这间的兼容(android3.0过后的版本)

    http://blog.csdn.net/lovecluo/article/details/8710174 在做我们自己的APP的时候,为了让APP看起来更加的好看,我们就需要将我们的自己的View做 ...

  4. iOS开发——UI篇OC篇&初始化图片方式

    初始化图片方式 一.读取图片 1.从资源(resource)读取 [cpp] view plaincopyprint?   UIImage* image=[UIImage imageNamed:@&q ...

  5. php中数组自定义排序

    php中数组自定义排序方法有很多,现在只提usort();不会保留原有键名. unsort调用方法就是unsrot($arr,func); 注意: 如果func是写在当前类中的话,那么调用的方式是 u ...

  6. yii2 rbac 设计

    tbl_auth_item 根据type存储认证项目...role.task.operation 游客... 不能操作任何模块 普通用户 ..biz_rule..需要登录 只有这里返回true,才能进 ...

  7. mysql 支持emoji

    1.修改my.cnf [client] default-character-set = utf8mb4 [mysqld] collation-server = utf8mb4_unicode_ci c ...

  8. 用 UIViewPropertyAnimator 编写动画

    [iOS 10 day by day] Day 1:开发 iMessage 的第三方插件 [iOS 10 day by day] Day 2:线程竞态检测工具 Thread Sanitizer < ...

  9. Hibernate的简单示例

    首先我们新建一个项目,Java项目或者是Javaweb项目都可以,然后把hibernate需要的jar导入,我用的jar包如下: 然后新建一个实体类Teacher.java并添加get和set方法: ...

  10. Android(java)学习笔记109:通过反射获取成员变量和成员方法并且使用

    一.反射获取成员变量并且使用: 1.获取字节码文件对象:         Class c = Class.forName("cn.itcast_01.Person"); 2.使用无 ...