这是利用人的视觉错觉来实现无限轮播,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. VHD更新命令(打补丁)

    DISM 查看vhd文件信息:dism /get-imageinfo /imagefile:e:\vhd\win2008r2.vhdxdism /get-imageinfo /imagefile:e: ...

  2. ssh 设置免password登录

    如果: 实现->操作机A机 要以用户"user1"身份.免password登录B机和C机? B机和C机 建立用户 user1 而且能够ssh 登录. A机设置: 1.安装ss ...

  3. SQL性能优化工具TKPROF

     全名为Trace Kernel Profile,用来格式化跟踪文件,是一个命令行工具. 主要的格式例如以下: tkprof tracefile outputfile - tracefile:要分 ...

  4. BZOJ 3931: [CQOI2015]网络吞吐量 最大流

    3931: [CQOI2015]网络吞吐量 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  5. Codeforces Gym 100418B 暴力

    Sum of sequencesTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/v ...

  6. delphi 11 编辑模式 浏览模式

    编辑模式 浏览模式 设置焦点 //在使用前需要Webbrowser已经浏览过一个网页 否则错误 uses MSHTML; ///获取Webbrowser编辑模式里面的内容procedure EditM ...

  7. TreeView1MouseMove

    procedure TForm1.TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,   Y: Integer); var   nod ...

  8. Asp.Net MVC 3【URLs, Routing,and Areas】续

    http://www.cnblogs.com/HuiTai/archive/2012/07/24/2597875.html 接着前面继续学习分享我们的路由. 现在我们把Global.asax文件里的R ...

  9. 有图有真相,分享一款网页版HTML5飞机射击游戏

    本飞机射击游戏是使用HTML5代码写的,尝试通过统一开发环境(UDE)将游戏托管在MM应用引擎,直接生成了网页版游戏,游戏简单易上手,非常适合用来当做小休闲打发时间. 游戏地址:http://flyg ...

  10. SAP BW 通过视图创建数据源(无单位)

    因业务明细表中数量没有单位,所以BW创建数据源时,需做增强 数据表: ZDB_H(抬头) ZDB_I(明细) ECC 系统中: 1.创建视图ZVDBWQ,因明细表中数量没有单位,所以创建视图时不包括数 ...