UIScrollerView当前显示3张图
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 + 1
    NSInteger 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张图
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
UIScrollerView当前显示3张图的更多相关文章
- Python中使用"subplot"在一张画布上显示多张图
		subplot(arg1, arg2, arg3) arg1: 在垂直方向同时画几张图 arg2: 在水平方向同时画几张图 arg3: 当前命令修改的是第几张图 t = np.arange(0,5,0 ... 
- prefuse学习(二)显示一张图
		1. 把数据以点连线的方式在画面中显示 2. 数据按照数据的性别属性使用不同的颜色 3. 鼠标左键可以把图在画面中拖动 4. 鼠标右键可以把图放大或者缩小 5. 鼠标单击某个数据上,该数据点 ... 
- R: 一页显示多张图的方法
		################################################### 问题:一页多图显示 18.4.30 怎么实现,在一页上画多幅图,并且安排图的大小.个数等?? ... 
- JavaScript实现轮播图(隔3秒显示一张图)
		<!DOCTYPE html><html> <head> <script> var time; function init(){ //获取div里面的东 ... 
- 一张图搞定OAuth2.0    在Office应用中打开WPF窗体并且让子窗体显示在Office应用上  彻底关闭Excle进程的几个方法    (七)Net Core项目使用Controller之二
		一张图搞定OAuth2.0 目录 1.引言 2.OAuth2.0是什么 3.OAuth2.0怎么写 回到顶部 1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常 ... 
- PIL合并4张图demo 800px以下的居中显示小例子
		from PIL import Image #新建一个空白文件 大小为1600*1600 颜色为白色 newIm= Image.new('RGB', (1600, 1600), 'white') #打 ... 
- 一张图看懂ANSYS17.0 流体 新功能与改进
		一张图看懂ANSYS17.0 流体 新功能与改进 提交 我的留言 加载中 已留言 一张图看懂ANSYS17.0 流体 新功能与改进 原创2016-02-03ANSYS模拟在线模拟在线 模拟在线 ... 
- 一张图读懂https加密协议
		搭建CA服务器和iis启用https:http://blog.csdn.net/dier4836/article/details/7719532 一张图读懂https加密协议 https是一种加密传输 ... 
- Javscript轮播      支持平滑和渐隐两种效果(可以只有两张图)
		原文:Javscript轮播 支持平滑和渐隐两种效果(可以只有两张图) 先上两种轮播效果:渐隐和移动 效果一:渐隐 1 2 3 4 效果二:移动 1 2 3 4 接下来,我们来大致说下整个轮播的思 ... 
随机推荐
- 【BZOJ 2118】 2118: 墨墨的等式 (最短路)
			2118: 墨墨的等式 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求 ... 
- 【BFS】Power Hungry Cows
			Power Hungry Cows Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 5522 Accepted: 1384 ... 
- [HDU4729]An Easy Problem for Elfness
			[HDU4729]An Easy Problem for Elfness 题目大意: 给你一棵\(n(n\le10^5)\)个点的树,树上每条边都有容量. \(m(m\le10^5)\)次询问,每次询 ... 
- Codeforces Round #127 (Div. 1) A. Clear Symmetry 打表
			A. Clear Symmetry 题目连接: http://codeforces.com/contest/201/problem/A Description Consider some square ... 
- Mac下JAVA开发环境搭建
			最近开始学习JAVA, 首先配置下环境! 1.Mac自带的jdk版本老了,需要到oracle官网去下载新的jdk,具体下载那个版本看个人需求,然后安装. 安装完成之后打开Terminal, 执行命 ... 
- dump备份mysql表
			Auth: Jin Date: 20140403 Content: #!/bin/bash - ### auth: Jin ### ### Desc: 备份输入库里的所有表,清理指定天前的备份文件 # ... 
- Phpstorm-sftp配置
			保存就可以了 随便点一个文件,右键就可以了,保存,上传快捷键 
- EF 通用数据层类
			EF 通用数据层父类方法小结 转载:http://www.cnblogs.com/yq-Hua/p/4165344.html MSSql 数据库 数据层 父类 增删改查: using System; ... 
- 【UEditor】关于导入ueditor-1.1.3.jar的问题---
			最近做一个项目,使用了百度的富文本框,本来是很简便易用的东西,在回显给富文本框的时候, var ue = UE.getEditor('container'); var noticeContent = ... 
- JCA 了解
			JCA (J2EE 连接器架构,Java Connector Architecture)是对 J2EE标准集的重要补充.因为它注重的是将 Java程序连接到非Java程序和软件包中间件的开发.连接器特 ... 
 
			
		