代码地址如下:
http://www.demodashi.com/demo/11173.html

WSLScrollView 功能描述:这是在继承UIView的基础上利用UIScrollerView进行了封装,支持循环轮播、自动轮播、自定义时间间隔、图片间隔、当前页码和图片大小,采用Block返回当前页码和处理当前点击事件的一个View。

一、效果图

二、实现过程

  • 逻辑结构示意图

①、首先像往常一样写一个基本的UIScrollerView,会得到下图:

    _scrollerView = [[UIScrollView alloc] init];_scrollerView.frame = CGRectMake((SELF_WIDTH - _currentPageSize.width) / 2, 0,    _currentPageSize.width, _currentPageSize.height);_scrollerView.delegate = self;_scrollerView.pagingEnabled = YES;_scrollerView.showsHorizontalScrollIndicator = NO;[self addSubview:_scrollerView];

  • 然后设置我们通常会忽略UIScrollerView的一个属性clipsToBounds为NO,默认是Yes,你会看到_scrollerView其它部分相邻的图片,但是你会发现那部分相邻的图片不会响应在它上面的任何触摸事件,因为那部分子视图超出了它的父视图,可以用响应链机制解决这个问题:
_scrollerView.clipsToBounds = NO;//处理超过父视图部分不能点击的问题,重写UIView里的这个方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {if ([self pointInside:point withEvent:event]) {CGPoint newPoint = [_scrollerView convertPoint:point fromView:self];for (UIImageView * imageView in _scrollerView.subviews) {if (CGRectContainsPoint(imageView.frame, newPoint)) {CGPoint newSubViewPoint = [imageView convertPoint:point fromView:self];return [imageView hitTest:newSubViewPoint withEvent:event];}}}return nil;
}

②、接下来实现循环的功能:我相信好多人也都会想到 《 4 + 0 - 1 - 2 - 3 - 4 + 0 》这个方案,也就是先在数组的最后插入原数组的第一个元素,再在第一个位置插入原数组的最后一个元素;得到如下图效果:(注意看:第一个向最后一个,最后向第一个循环过渡的时候有个Bug哦)

    self.imageArray = [NSMutableArray arrayWithArray:_images];[self.imageArray addObject:_images[0]];[self.imageArray insertObject:_images.lastObject atIndex:0];//初始化时的x偏移量要向前多一个单位的_currentPageSize.width_scrollerView.contentOffset = CGPointMake(_currentPageSize.width * (self.currentPageIndex + 1), 0);

  • 解决上述Bug的方案就是利用UIScrollView的两个代理方法;在前后循环过渡处,刚开始拖拽时就在Bug的位置画上对应的视图;即《 3 + 4 + 0 - 1 - 2 - 3 - 4 + 0 + 1》,结束拖拽之后,再改变UIScrollView的contentOffset,不带动画;
//开始拖拽时执行
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{//开始拖拽时停止计时器[self.timer invalidate];self.timer = nil;// 3 + 4 + 0 - 1 - 2 - 3 - 4 + 0 + 1NSInteger index = scrollView.contentOffset.x/_currentPageSize.width;//是为了解决循环滚动的连贯性问题if (index == 1) {[self.scrollerView addSubview:self.lastView];}if (index == self.imageArray.count - 2) {[self.scrollerView addSubview:self.firstView];}
}//结束拖拽时执行
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{NSInteger index = scrollView.contentOffset.x/_currentPageSize.width;//停止拖拽时打开计时器if (_isTimer) {[self statrScroll:_second];}//是为了解决循环滚动的连贯性问题if (index == 0) {scrollView.contentOffset = CGPointMake(_currentPageSize.width * (self.imageArray.count - 2) , 0);}if (index == self.imageArray.count - 1) {scrollView.contentOffset = CGPointMake(_currentPageSize.width  , 0);}
}

③实现定时器自动循环轮播功能,需要解决的问题就是首尾过渡的时候,

如下图所示:解决的思路和上述类似,主要代码已标明→WSLScrollView

- (void)statrScroll:(CGFloat)second{if (_timer == nil && _isTimer) {_timer = [NSTimer scheduledTimerWithTimeInterval:second target:self selector:@selector(autoNextPage) userInfo:nil repeats:YES];}
}- (void)autoNextPage{[_scrollerView setContentOffset:CGPointMake( _currentPageSize.width * (_currentPageIndex + 1 + 1), 0) animated:YES]; if (_currentPageIndex + 2 == self.imageArray.count - 1) {//是为了解决自动滑动到最后一页再从头开始的连贯性问题[_scrollerView addSubview:self.firstView];}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{CGFloat index = scrollView.contentOffset.x/_currentPageSize.width;if (index == 0 ) {_currentPageIndex = self.imageArray.count - 1- 2;}else if(index < 1){}else if(index == self.imageArray.count - 1 || index == 1){_currentPageIndex = 0;//是为了解决自动滑动到最后一页再从头开始的连贯性问题[_scrollerView setContentOffset:CGPointMake( _currentPageSize.width , 0) animated:NO];  }else if(index == ceil(index)){_currentPageIndex = index - 1 ;}if (self.scrollEndBlock != nil) {self.scrollEndBlock(_currentPageIndex);}
}

三、项目结构图

UIScrollerView当前显示3张图

代码地址如下:
http://www.demodashi.com/demo/11173.html

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

UIScrollerView当前显示3张图相关推荐

  1. prefuse学习(二)显示一张图

    1.  把数据以点连线的方式在画面中显示 2.  数据按照数据的性别属性使用不同的颜色 3.  鼠标左键可以把图在画面中拖动 4.  鼠标右键可以把图放大或者缩小 5.  鼠标单击某个数据上,该数据点 ...

  2. ctf解题--当眼花的时候,会显示两张图(隐写)

    题目 不信? 你试试 解题链接: http://ctf5.shiyanbar.com/stega/final.png 解题 下载图片 wget http://ctf5.shiyanbar.com/st ...

  3. vue2的堆叠轮播图 (5张图 错开叠加,来回切换)

    先上图: 这是一个js文件,需要在vue项目中引用这个,前提是你要下载swiper插件. export class Swiper {constructor(options) {this.$option ...

  4. python画多图在一个图_python pyecharts 实现一个文件绘制多张图

    Grid并行显示多张图 注意: 第一个图需为 有 x/y 轴的图,即不能为 Pie,其他位置顺序任意 from pyecharts import Bar, Line, Scatter, EffectS ...

  5. matlab两个曲线的名称怎么显示出来的,求MATLAB的高手,怎么把两张仿真曲线合并显示在一张图上?...

    求MATLAB的高手,怎么把两张仿真曲线合并显示在一张图上? 关注:194  答案:5  手机版 解决时间 2021-02-10 14:48 提问者终究是陌生了 2021-02-09 16:38 程序 ...

  6. css多图标在一张图内如何正确显示它们

    图标在一张图内做法 参考QQ微博的做法:icon:两张图标上下结构在一张图内,需要分别显示在两个地方. icon: 需做成的样子: .header .qqwb ul li{ display: inli ...

  7. 使用Python中的matplotlib将多个图片显示到一张图内

    在我们写论文或是汇报时,经常需要整合所得到的可视化数据结果,插入我们的论文中.如下所示的情况,我们需要将四个相关的弹性模量预测结果在一张图里展示. 使用matplotlib库中的子图(subplot) ...

  8. python Matplotlib 可视化总结归纳(二) 绘制多个图像单独显示多个函数绘制于一张图

    1. 绘制多个图像单独显示(subplot) import numpy as np import matplotlib.pyplot as plt #创建自变量数组 x= np.linspace(0, ...

  9. LaTeX两张图并排显示

    一.需要引入的包 \usepackage{caption} % 图片脚注 \usepackage{graphicx} \usepackage{caption} \usepackage{subfigur ...

最新文章

  1. AlertDialog具体解释
  2. 【完整代码】使用Semaphore实现限流代码示例
  3. opengl2 vtk 编译_编译和使用VTK时值得注意的点(待续)
  4. 软件系统换服务器地址,天正软件客户端修改服务器地址
  5. c++调用Libsvm
  6. python从零开始学爬虫_从零开始学爬虫(爬取豆瓣),一看就会
  7. Latex中将多个eps图片合并成一幅eps的代码和方法
  8. 如何删除vc2013上配置好的opencv
  9. PBR 六 材质参数
  10. 软件开发人员是一种很棒的职业选择的五大理由
  11. 苹果关掉200m限制_苹果下载超过200兆怎么设置
  12. 日系插画学习笔记(三):光影与结构
  13. 简明扼要聊聊 Vue3.0 的 Composition API 是啥东东!
  14. 在matlab上利用fft进行信号频谱分析_使用示波器进行信号频谱分析(FFT)的设置教学...
  15. 中大近代物理实验实验报告(LaTeX实现)
  16. CAD标注如何提取下来?这样提取很容易
  17. 超级壁纸android,超级壁纸大全app下载
  18. Linux上监控应用程序启动 (hook execve系统调用)
  19. 一个可以绑定多个天翼云网盘的目录列表程序,支持视频播放
  20. 离散行业和流程行业的区别

热门文章

  1. 9.FreeRTOS学习笔记-任务通知
  2. 12015.linux通过代码或命令形式操作内存/dev/mem
  3. 飞桨PaddleHub实现皮影戏
  4. 截取年月日在hana中怎么写_获取Sting类型格式-日期中的年月日
  5. apb外设怎么分配地址
  6. 【绪论】——声呐概述
  7. 【声传播】——角谱理论、模式理论及三维傅里叶变换
  8. Nginx基本数据结构之ngx_hash_t
  9. 3.3.4.5. 日期计算
  10. Linux内核网络协议栈1- socket文件系统注册