iOS广告Banner,使用三个ImgView无限循环轮播
来源:互联网 发布:资金盘系统源码 编辑:程序博客网 时间:2024/06/18 17:34
图片加载使用 SDWebImage 第三方库。
WTCycleRollView.h
#import <UIKit/UIKit.h>@interface WTCycleRollView : UIView@property (nonatomic, assign) NSTimeInterval rollTimeInterval;/** 返回 WTCycleRollView 对象 @param frame 位置尺寸 @return WTCycleRollView 对象 */+ (instancetype)cycleRollViewWithFrame:(CGRect)frame;/** 设置图片源、是否自动滚动、点击图片的回调 @param imgUrls 图片源 @param autoCycleRoll 是否自动滚动 @param clickImgBlock 点击图片的回调 */- (void)setImgUrls:(NSArray *)imgUrls autoCycleRoll:(BOOL)autoCycleRoll clickImgBlock:(void(^)(NSInteger selectedIndex))clickImgBlock;/** 暂停自动滚动 */- (void)pauseCycleRoll;/** 开始自动滚动【在暂停的状态下】 */- (void)startCycleRoll;@end
WTCycleRollView.m
#import "WTCycleRollView.h"#import "UIImageView+WebCache.h"typedef void(^ClickImgBlock) (NSInteger);@interface WTCycleRollView () <UIScrollViewDelegate>@property (nonatomic, strong) UIScrollView *scrollView;@property (nonatomic, strong) UIPageControl *pageControl;@property (nonatomic, strong) UIImageView *leftImgView;@property (nonatomic, strong) UIImageView *middleImgView;@property (nonatomic, strong) UIImageView *rightImgView;/** 图片源 */@property (nonatomic, strong) NSArray *imgUrls;/** 当前显示的图片的 Index */@property (nonatomic, assign) NSInteger showIndex;/** 点击图片的回调 Block */@property (nonatomic, strong) ClickImgBlock clickImgBlock;/** 自动滚动的计时器 */@property (nonatomic, strong) NSTimer *cycleRollTimer;/** 是否手动滑动 */@property (nonatomic, assign) BOOL manual;@end@implementation WTCycleRollView/** 默认循环滚动的时间间隔(s) */static NSTimeInterval const DefaultRollTimeInterval = 4;#pragma mark - 懒加载- (UIImageView *)leftImgView { if (!_leftImgView) { _leftImgView = [[UIImageView alloc] initWithFrame:self.bounds]; } return _leftImgView;}- (UIImageView *)middleImgView { if (!_middleImgView) { _middleImgView = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds), 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))]; /** 为中间正在显示的 ImgView 添加点击事件 */ UITapGestureRecognizer *tapGr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickImgView)]; [_middleImgView setUserInteractionEnabled:YES]; [_middleImgView addGestureRecognizer:tapGr]; } return _middleImgView;}- (UIImageView *)rightImgView { if (!_rightImgView) { _rightImgView = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds) * 2, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))]; } return _rightImgView;}- (UIScrollView *)scrollView { if (!_scrollView) { _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; _scrollView.delegate = self; _scrollView.showsHorizontalScrollIndicator = NO; _scrollView.pagingEnabled = YES; } return _scrollView;}- (UIPageControl *)pageControl { if (!_pageControl) { _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.bounds) - 20, CGRectGetWidth(self.bounds), 20)]; _pageControl.layer.shadowOpacity = 0.3; _pageControl.layer.shadowOffset = CGSizeMake(0, 0); } return _pageControl;}#pragma mark - 初始化- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self addSubview:self.scrollView]; [_scrollView addSubview:self.leftImgView]; [_scrollView addSubview:self.middleImgView]; [_scrollView addSubview:self.rightImgView]; [self addSubview:self.pageControl]; } return self;}#pragma mark - 类方法 返回 WTCycleRollView+ (instancetype)cycleRollViewWithFrame:(CGRect)frame { return [[self alloc] initWithFrame:frame];}#pragma mark - 设置图片显示,自动滚动- (void)setImgUrls:(NSArray *)imgUrls autoCycleRoll:(BOOL)autoCycleRoll clickImgBlock:(void (^)(NSInteger))clickImgBlock { _clickImgBlock = clickImgBlock; _imgUrls = imgUrls; _pageControl.numberOfPages = [imgUrls count]; _pageControl.currentPage = 0; if ([_imgUrls count] > 1) { [_leftImgView sd_setImageWithURL:[NSURL URLWithString:[imgUrls lastObject]]]; [_middleImgView sd_setImageWithURL:[NSURL URLWithString:[imgUrls firstObject]]]; [_rightImgView sd_setImageWithURL:[NSURL URLWithString:[imgUrls objectAtIndex:1]]]; _scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) * 3, 0); [_scrollView setContentOffset:CGPointMake(CGRectGetWidth(self.bounds), 0)]; if (autoCycleRoll) { [self stopTimer]; _cycleRollTimer = [NSTimer scheduledTimerWithTimeInterval:DefaultRollTimeInterval target:self selector:@selector(cycleRoll) userInfo:nil repeats:YES]; } else { [self stopTimer]; } } else { _scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds), 0); [_leftImgView removeFromSuperview]; [_rightImgView removeFromSuperview]; if ([imgUrls count]) { [_middleImgView sd_setImageWithURL:[NSURL URLWithString:[imgUrls firstObject]]]; _middleImgView.frame = self.bounds; } }}#pragma mark - 自动滚动的事件- (void)cycleRoll { // 当手动滚动的时候,跳过此次循环 if (_manual) { _manual = NO; } else { [_scrollView setContentOffset:CGPointMake(CGRectGetWidth(self.bounds) * 2, 0) animated:YES]; }}- (void)clickImgView { !_clickImgBlock ? : _clickImgBlock(_showIndex);}#pragma mark - UIScrollView Delegate/** ScrollView 滑动减速停止回调【这里根据 ScrollView 的偏移量来判断是向左滑还是向右滑】 */- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if ([_imgUrls count]) { CGFloat offsetX = scrollView.contentOffset.x; if (offsetX <= 0) { // 向右滑,即将显示上一张图片(若当前显示的是第一张,则上一张为最后一张) self.showIndex = (_showIndex + [_imgUrls count] - 1) % [_imgUrls count]; } else if (offsetX >= CGRectGetWidth(self.bounds) * 2) { // 向右滑,即将显示下一张图片(若当前显示的是最后一张,则下一张为第一张) self.showIndex = (_showIndex + 1) % [_imgUrls count]; } }}/** 自动滑动【即代码设置的滚动(setContentOffset:animated:)】,不会直接调用上述方法(滑动减速停止回调),但会调用此方法,在此方法再调用上述方法便可 */- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { [self scrollViewDidEndDecelerating:_scrollView];}/** 手动滑动手指触摸屏幕的回调,暂停计时器 */- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self pauseCycleRoll];}/** 手动滑动手指离开屏幕的回调,开启计时器 */- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { _manual = YES; // 这里开启计时器会立即调用循环滚动的方法,用户体验不好,所以设置此参数,让其跳过这次循环滚动事件 [self startCycleRoll];}/** 根据 ScrollView 偏移量设置 PageControl 的当前页 */- (void)scrollViewDidScroll:(UIScrollView *)scrollView { if ([_imgUrls count]) { CGFloat offsetX = scrollView.contentOffset.x; if (offsetX <= CGRectGetWidth(self.bounds) * 0.5) { _pageControl.currentPage = (_showIndex + [_imgUrls count] - 1) % [_imgUrls count]; } else if (offsetX >= CGRectGetWidth(self.bounds) * 1.5) { _pageControl.currentPage = (_showIndex + 1) % [_imgUrls count]; } else { _pageControl.currentPage = _showIndex; } }}#pragma mark - 设置当前显示的图片- (void)setShowIndex:(NSInteger)showIndex { _showIndex = showIndex; // 不管向左滑还是向右滑,这里立即将将要显示的图片展示在中间的 ImgView 上,然后马上将 ScrollView 偏移量设置到显示中间的 ImgView // 由于代码执行及屏幕显示渲染非常快,肉眼几乎看不出,所以这样就达到了效果 [_leftImgView sd_setImageWithURL:[NSURL URLWithString:_imgUrls[(_showIndex + [_imgUrls count] - 1) % [_imgUrls count]]]]; [_middleImgView sd_setImageWithURL:[NSURL URLWithString:_imgUrls[showIndex]]]; [_rightImgView sd_setImageWithURL:[NSURL URLWithString:_imgUrls[(showIndex + 1) % [_imgUrls count]]]]; // 切记,这里设置 ScrollView 偏移量不能用动画 [_scrollView setContentOffset:CGPointMake(CGRectGetWidth(self.bounds), 0)];}#pragma mark - 自动滚动时,计时器的暂停与启动/** 暂停计时器 */- (void)pauseCycleRoll { if (_cycleRollTimer) { [_cycleRollTimer setFireDate:[NSDate distantFuture]]; }}/** 启动定时器【在计时器暂停状态下】 */- (void)startCycleRoll { if (_cycleRollTimer) { [_cycleRollTimer setFireDate:[NSDate distantPast]]; }}#pragma mark - 停止计时器,并释放- (void)stopTimer { if (_cycleRollTimer) { [_cycleRollTimer invalidate]; _cycleRollTimer = nil; }}#pragma mark - WTCycleRollView 释放的时候 停止计时器,并释放,否则会造成内存泄漏- (void)dealloc { [self stopTimer];}@end
阅读全文
0 0
- iOS广告Banner,使用三个ImgView无限循环轮播
- Banner实现广告无限轮播
- Android无限循环轮播广告位Banner
- Android无限循环轮播广告位Banner
- Android无限循环轮播广告位Banner
- 自定义Banner轮播广告(真*无限循环无卡顿&设置切换速度)
- 广告无限轮播+自动轮播 Banner
- Android 实现广告Banner循环轮播
- Android 实现广告Banner循环轮播
- ios 滚动视图,滚动广告,无限循环轮播
- 广告栏(自动轮播,无限循环)-图片轮播控件Banner的简单使用总结
- Banner无限轮播
- Banner无限轮播
- banner无限轮播
- banner无限轮播
- Banner无限轮播
- Banner无限轮播
- banner无限轮播
- 迟到的=·=幽灵猎手
- mac JDK9的安装与环境配置以及Tomcat安装错误问题的解决
- 单源最短路径
- 各种Java加密算法
- HTML 面试常见知识点
- iOS广告Banner,使用三个ImgView无限循环轮播
- 通过XMLHttpRequest加载外部图片文件或数据
- CSS面试常见知识点
- JS原型链、继承的问题与解决:组合继承、借用构造函数(未完)
- inux必学的命令
- 打印数字
- SpringMVC视图解析器InternalResourceViewResolver
- OpenJ_Bailian
- given final block not properly padded aes