这两天使用Reveal工具查看"手机淘宝"App的UI层次时,发现其图片轮播使用了三个UIButton的复用来实现的图片循环无缝滚动。于是乎就有了今天这篇博客,看到“手机淘宝”这个幻灯片的UI层级时,就想要动手使用三个Button来实现一下,当然本篇博客使用是Swift语言,思路就是使用三个Button进行图片无限轮播。之前发过两篇关于图片轮播的博客,一个是没有使用ImageView复用的,一个是使用两张ImageView进行复用来实现图片轮播的,都是使用的Objective-C实现的,并在github上进行了代码分享。

本篇博客就是介绍如何去一步步的封装这个三个Button的无限轮播的组件的。在实现时将该无限轮播的组件进行了封装,需要你在实例化该组件后,传入一个存放图片地址的数组,数组中可以是本地图片的名字,也可以是一个网络图片的地址。如果是网络图片的地址,组件中会使用NSRULSession并采用合适的缓存策略从网络加载图片,加载完后在我们的组件上进行显示。废话少说,进入我们今天的主题。

今天的博客完全是个人兴趣爱好,也不是公司中项目要使用的缘故才去实现的。就是看到了淘宝中的轮播图,从UI层级上感觉这样可以实现,于是乎就打开Xcode,创建个Swift工程实现一把,过程还是蛮愉快的。当然今天封装组件的名称是以公司的名称首字母做的前缀了,这也便于在以后的工作中遇到该问题直接拿过来就用呢。

一、对“手机淘宝”UI层次的简单分析

下方截图就是当时我用Reveal工具查看的手机淘宝App的UI层级,下方只是幻灯片的部分。下方整个页面是使用UICollectionView来实现的了,下方的幻灯片所在的UIScrollView就放在UICollectionView上的一个Cell上。当然这不是我们今天的重点,我们将目光转移到左边红框中的数学层级上。可以明显的看出UIScrollView上贴了三个UIButton,而每个UIButton上又贴了一个UIImageView。

需要注意的一点是你看到UIButton是三个Button的中间一个,从下面UI视图中我们不难分析出,无论当前显示的是第几张图片,你看到的永远是中间Button上显示的图片。也就是将要显示的图片放到中间的Button上,左边的Button存放上一张图片,右边的Button存放下一张图片。当用户左划或者右划后,我们要做的事情就是将中间按钮放到可视区,并且设置成要显示的图片,当然左右两个Button都得设置成相应的图片,便于用户下次移动。当然这只是我的个人猜测,上面这种思路使用代码来实现是完全可行的,并且可以实现无循环无缝滚动了。

当然,上面说的原理比较简单,具体使用代码实现起来还是需要许多细节的。比如用户滑动时定时器的挂起和唤醒,用户左右滑动方向的记录,便于自动轮播时的方向与用户上次滑动的方向一致,异步加载网络请求图片,加载后显示在相应的Button上,通过Closure回调出用户点击事件可当前图片的索引信息等等需要注意的细节。敲代码也有几年时间了,有一点感触挺深的就是“说和做”完全是两码事,也就是你有思路和你把你的思路用代码实现,这是完全不同的概念。当然正确的思路固然重要,但是不去实现再好的思路也是枉费,实践出真知吗。说这么多,有回到了说与做的问题上,这话题就不多讨论了,高执行力,高自制力好处是多多的。言归正传,回到今天的主题。

  

二、从“原理图”中来看今天轮播的主题

下方就是今天要实现的轮播组件的原理图,思路就是这么个思路,要实现起来还得靠代码往上摞呢。下方解析图是以轮播5张图片为例。初始化状态是你看到的是第一张图片,第一张图片位于三个Button的中间,然后左边就是最后一张图片,右边是第二张图片。如果用户想右滑动显示的第二张图片(对应着下方的第一步),当第二张图片已经完全显示出来后,我们要做的第一件事情就是将用户移动的位置进行复位,也就是将第二个Button移动到显示的位置,然后设置按钮上显示相应的图片。第一个按钮就显示当前图片的前一张图片,如果当前显示的是第一张图片,那么第一个按钮上就显示最后一张图片。第三个按钮就显示当前图片的下一张图片,如果当前显示的图片是最后一张图片的话,那么第三个按钮上就显示第一张图片。这样就可以图片轮播了。

  

三、该自定义控件的视图层级

下图就是我们按照上面的思路,使用ScrollView上添加3个Button来实现的图片轮播,无缝滚动的效果还是蛮OK的。在下方运行效果中美女图片是从本地加载的,而风景图片是使用NSURLSession和GCD的东西并行异步的从网络获取的,获取完后再加载到相应Button的ImageView上。下方就是我们本篇博客相关Demo的运行效果,单从效果上来看,与之前所发布的图片轮播没有什么区别,但是其内部实现机制还是有较大区别的。接下来就逐步的看一下代码实现。

  

上面是运行效果,下方是UI的层级。当然也是用我们强大的Reveal来查看的了,下方红框中就是我们图片轮播的视图层级。该视图层级与“手机淘宝”上是一致的,都是在UIScrollView上贴了三个Button,然后在每个Button上贴了一个ImageView。层级比较简单,而你看到的当然是中间Button上的ImageView了,更多细节请看下图。

  

四、代码实现

运行效果看完了,UI层级结构也看完了,那么接下来就到了我们代码实现的时刻了。下方从组件的调用方式入手,逐步的去看一下上述效果是如何实现的。

1.上述组件的调用方式

下方代码段就是上述组件的实例化和调用方式,首先进行初始化,然后将该组件添加到父视图上。之后将要显示的图片数组imagesNameArray传入组件中,最后设置一下组件的闭包回调即可,该回调将每个按钮点击的时间回调给组件的使用者,该Closure的参数是当前点击按钮上所显示的Image的索引,说白了也就是你当前点击的第几张图片。

  

在调用组件时,传入给组件的参数是一个数组,下方代码就是我们初始化imagesNameArray的函数。从该代码段中我们不难看出,该数组中存储的有本地图片的名字,也有UIImage的对象,也有网络图片的URL。将含有三种元素的数组传给我们的组件实例,这些数组中的资源就可以按照数组中的顺序依次的循环轮播了。

  

2.上述组件的核心代码

组件调用方式还是蛮简单的,看完调用方式,接下来来看一下具体的代码实现。下方是我们组件中比较核心的实现部分。

(1).异步加载网络图片

下方代码段就是遍历我们的ImagesNameArray,找出该数组中所有的网络图片的URL,每找到一个URL就开启一个线程来请求该地址中的图片。下方的queue是并行队列,此处当然是并行队列的异步执行了。关于GCD的东西,请参考之前的博客《Grand Central Dispatch详解》。

  

下方代码段就是requestImage()方法中的内容了,该方法中使用NSSession并配置相应的缓存策略来请求网络图片。加载完图片后,将ImagesNameArray中相应的URL替换成相应的UIImage对象,然后在主线程中更新UI显示相应的图片,具体代码如下所示。

  

(2)moveImageView()方法的实现

该方法负责将按钮归位与赋值,该方法对应着上述原理图的第二和第三步。上面网络请求完一张图片后就会调用该方法更新UI。该方法的具体实现如下所示。下方代码中首先获取当前显示的页数,也就是当前显示的Image的索引,然后将第二个Button移动到可视区,最后调用setButtonImage()函数将每个Button上的ImageView设置成相应的Image。

  

(3)、定时器的实现

图片要隔段时间自动轮播,此处我们使用的是dispatch_source中的定时器类型来实现的自动轮播。下方就是我们定时器的实现,如下所示,代码比较简单,在此就不做过多的赘述了,创建完定时器我们不要忘了对定时器的source进行唤醒即可。

  

当用户进行手动切换时,我们要对定时器进行相应的挂起和唤醒操作。也就是说当用户开始滑动时我们要对定时器进行挂起,当用户滑动结束后要对定时器进行唤醒。当然这些都是在ScrollView相应的代理方法中进行处理的,具体如下所示:

  

(4)、滑动结束后更新按钮的位置和图片

无论是手动滑动,还是使用定时器滑动,滑动结束后我们都需要更新一下按钮的位置和按钮上要显示的图片。所以我们还需要使用到UIScrollView上的一个代理方法,那就是scrollViewDidScroll(),在该代理方法中我们调用了moveImage()方法来更新Button的位置和Button上ImageView要显示的图片信息。没有这个方法,图片就动不起来了,具体代码如下所示:

  

上述是该Demo的核心代码,更为详细的代码请移步于github: https://github.com/lizelu/CEImagesScrollDisplay, 因本篇博客篇幅有限,更具体的细节在此就不做过多赘述了,Demo已在上述github上进行分享。

iOS开发之三个Button实现图片无限轮播(参考手机淘宝,Swift版)的更多相关文章

  1. iOS开发之ImageView复用实现图片无限轮播

    在上篇博客中iOS开发之多图片无缝滚动组件封装与使用给出了图片无限轮播的实现方案之一,下面在给出另一种解决方案.今天博客中要说的就是在ScrollView上贴两个ImageView, 把ImageVi ...

  2. iOS 两种不同的图片无限轮播

    代码地址如下:http://www.demodashi.com/demo/11608.html 前记 其实想写这个关于无限轮播的记录已经很久很久了,只是没什么时间,这只是一个借口,正如:时间就像海绵, ...

  3. Android实现广告页图片无限轮播

    一.概述 对于一个联网的Android应用, 首页广告无限轮播基本已经成为标配了. 那么它是怎么实现的呢? 有几种实现方式呢? 二.无限轮播的实现 1.最常规的手段是用 ViewPager来实现 2. ...

  4. axure 动态面板实现图片轮播效果(淘宝)

    淘宝中经常可以看到店铺中的图片轮播效果,本经验将通过axure7.0实现 工具/原料   axure7.0 方法/步骤     下载需要轮播的图片   将图片引入至axure中,将引入的第一张图片转为 ...

  5. iOS实现图片无限轮播之使用第三方库SDCycleScrollView(转)

    下载链接:github不断更新地址:https://github.com/gsdios/SDCycleScrollView #import "ViewController.h" # ...

  6. iOS开发进阶 - 日志输出框架CocoaLumberjack与XcodeColors插件的简单使用(swift版)

    CocoaLumberjack是Mac和iOS上一个集快捷.简单.强大和灵活于一身的日志框架.XcodeColors是用于控制台着色的工具,配合着CocoaLumberjack用有更好的效果,不废话, ...

  7. ViewPager—02图片无限轮播

    布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t ...

  8. iOS开发UI篇—Button基础

    iOS开发UI篇—Button基础 一.简单说明 一般情况下,点击某个控件后,会做出相应反应的都是按钮 按钮的功能比较多,既能显示文字,又能显示图片,还能随时调整内部图片和文字的位置 二.按钮的三种状 ...

  9. iOS开发UI篇—无限轮播(循环利用)

    iOS开发UI篇—无限轮播(循环利用) 一.无限轮播  1.简单说明 在开发中常需要对广告或者是一些图片进行自动的轮播,也就是所谓的无限滚动. 在开发的时候,我们通常的做法是使用一个UIScrollV ...

随机推荐

  1. Java多线程基础学习(二)

    9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...

  2. Webpack 配置摘要

    open-browser-webpack-plugin 自动打开浏览器 html-webpack-plugin 通过 JS 生成 HTML webpack.optimize.UglifyJsPlugi ...

  3. ASP.NET Core中如影随形的”依赖注入”[下]: 历数依赖注入的N种玩法

    在对ASP.NET Core管道中关于依赖注入的两个核心对象(ServiceCollection和ServiceProvider)有了足够的认识之后,我们将关注的目光转移到编程层面.在ASP.NET ...

  4. html5 与视频

    1.视频支持格式. 有3种视频格式被浏览器广泛支持:.ogg,.mp4,.webm. Theora+Vorbis=.ogg  (Theora:视频编码器,Vorbis:音频编码器) H.264+$$$ ...

  5. 用django创建一个项目

    首先你得安装好python和django,然后配置好环境变量,安装python就不说了,从配置环境变量开始 1.配置环境变量 在我的电脑处点击右键,或者打开 控制面板\系统和安全\系统 -> 左 ...

  6. python10作业思路及源码:类Fabric主机管理程序开发(仅供参考)

    类Fabric主机管理程序开发 一,作业要求 1, 运行程序列出主机组或者主机列表(已完成) 2,选择指定主机或主机组(已完成) 3,选择主机或主机组传送文件(上传/下载)(已完成) 4,充分使用多线 ...

  7. 如何使用dos命令打开当前用户、当前日期、当前时间以及当前用户加当前时间?

    1.dos命令安装mysqld --stall.启动net start mysql.进入MySQL数据库mysql -uroot -p后,输入select user();当前用户 select cur ...

  8. Web应用之LAMP源码环境部署

    一.LAMP环境的介绍 1.LAMP环境的重要性 思索许久,最终还是决定写一篇详细的LAMP的源码编译安装的实验文档,一来是为了给自己一个交代,把技术进行系统的归纳,将技术以极致的形式呈现出来,做为一 ...

  9. Ubuntu1604下安装Liggghts及CFDEM Coupling

    部分内容参考http://www.linuxdiyf.com/linux/16315.html LIGGGHTS是一款开源的DEM软件,来自于著名的分子动力学软件LAMMPS,目前借助于CFDEM C ...

  10. Hbase安装和错误

    集群规划情况: djt1 active Hmaster djt2 standby Hmaster djt3 HRegionServer 搭建步骤: 第一步:配置conf/regionservers d ...