Swift - 图片循环轮播组件的实现(附样例)

82 篇文章 1 订阅
图片的无限循环轮播功能常常用在广告或者新闻展示上面,本文演示如何实现一个  iOS 系统下的图片轮播组件。

1,组件功能介绍
(1)每隔一段时间,轮播器就会自动滚动到下一张图片。如果当前是最后一张图片的话,则又滚动回第一张图片。这样无限循环下去。
(2)在组件下方位置有页控制器(小圆点),显示图片数量和当前的位置。
(3)除了自动轮播,我们还可以通过手动滑动组件来显示上一张,下一张图片。手动控制滚动的时候自动轮播功能停止,手动滚动结束后自动轮播功能又自动启用。
(4)点击图片我们可以获取到当前图片的位置索引,便于我们后续操作。这里直接将索引值显示出来。

2,组件效果图
      原文:Swift - 图片循环轮播组件的实现(附样例)       原文:Swift - 图片循环轮播组件的实现(附样例)

3,组件实现原理
(1)我们在一个  scrollerView 中横向放置三个并排的  imageView。管多少张图片都是交替使用这三个  imageView 来显示。
(2)每次图片滚动结束的时候,计算当前显示的图片索引值。并重置三个  imageView 里的图片和位置。
(3)由于图片可以通过网络加载,这里我用了一个第三方的图片库: ImageHelper。可以自动帮我们实现图片缓存,避免重复加载。(关于  ImageHelper,可以参考我之前写过的这篇文章: Swift - 图片处理库AFImageHelper详解
(4)在图片未加载出来的时候,其位置上会先显示一张加载提示图片。这里我同样借助  ImageHelper,将一段提示文字转成  Image,用来作为加载完毕前的提示。
原文:Swift - 图片循环轮播组件的实现(附样例)

4,组件代码
整个组件只有一个  swift 文件( SliderGalleryController.swift),里面包含一个组件实现类: SliderGalleryController。以及相关协议: SliderGalleryControllerDelegate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
import  UIKit
 
//图片轮播组件代理协议
protocol  SliderGalleryControllerDelegate {
     //获取数据源
     func  galleryDataSource()->[ String ]
     //获取内部scrollerView的宽高尺寸
     func  galleryScrollerViewSize()-> CGSize
}
 
//图片轮播组件控制器
class  SliderGalleryController UIViewController , UIScrollViewDelegate {
     //代理对象
     var  delegate :  SliderGalleryControllerDelegate !
     
     //屏幕宽度
     let  kScreenWidth =  UIScreen .main.bounds.size.width
     
     //当前展示的图片索引
     var  currentIndex :  Int  = 0
     
     //数据源
     var  dataSource : [ String ]?
     
     //用于轮播的左中右三个image(不管几张图片都是这三个imageView交替使用)
     var  leftImageView , middleImageView , rightImageView :  UIImageView ?
     
     //放置imageView的滚动视图
     var  scrollerView :  UIScrollView ?
     
     //scrollView的宽和高
     var  scrollerViewWidth :  CGFloat ?
     var  scrollerViewHeight :  CGFloat ?
     
     //页控制器(小圆点)
     var  pageControl :  UIPageControl ?
     
     //加载指示符(用来当iamgeView还没将图片显示出来时,显示的图片)
     var  placeholderImage: UIImage !
     
     //自动滚动计时器
     var  autoScrollTimer: Timer ?
     
     override  func  viewDidLoad() {
         super .viewDidLoad()
 
         //获取并设置scrollerView尺寸
         let  size :  CGSize  self .delegate.galleryScrollerViewSize()
         self .scrollerViewWidth = size.width
         self .scrollerViewHeight = size.height
 
         //获取数据
         self .dataSource =   self .delegate.galleryDataSource()
         //设置scrollerView
         self .configureScrollerView()
         //设置加载指示图片
         self .configurePlaceholder()
         //设置imageView
         self .configureImageView()
         //设置页控制器
         self .configurePageController()
         //设置自动滚动计时器
         self .configureAutoScrollTimer()
         
         self .view.backgroundColor =  UIColor .black
     }
     
     //设置scrollerView
     func  configureScrollerView(){
         self .scrollerView =  UIScrollView (frame:  CGRect (x: 0,y: 0,
                 width:  self .scrollerViewWidth!, height:  self .scrollerViewHeight!))
         self .scrollerView?.backgroundColor =  UIColor .red
         self .scrollerView?.delegate =  self
         self .scrollerView?.contentSize =  CGSize (width:  self .scrollerViewWidth! * 3,
                                                 height:  self .scrollerViewHeight!)
         //滚动视图内容区域向左偏移一个view的宽度
         self .scrollerView?.contentOffset =  CGPoint (x:  self .scrollerViewWidth!, y: 0)
         self .scrollerView?.isPagingEnabled =  true
         self .scrollerView?.bounces =  false
         self .view.addSubview( self .scrollerView!)
         
     }
     
     //设置加载指示图片
     func  configurePlaceholder(){
         //这里我使用ImageHelper将文字转换成图片,作为加载指示符
         let  font =  UIFont .systemFont(ofSize: 17.0, weight:  UIFontWeightMedium )
         let  size =  CGSize (width:  self .scrollerViewWidth!, height:  self .scrollerViewHeight!)
         placeholderImage =  UIImage (text:  "图片加载中..." , font:font,
                                    color: UIColor .white, size:size)!
     }
     
     //设置imageView
     func  configureImageView(){
         self .leftImageView =  UIImageView (frame:  CGRect (x: 0, y: 0,
                     width:  self .scrollerViewWidth!, height:  self .scrollerViewHeight!))
         self .middleImageView =  UIImageView (frame:  CGRect (x:  self .scrollerViewWidth!, y: 0,
                     width:  self .scrollerViewWidth!, height:  self .scrollerViewHeight! ));
         self .rightImageView =  UIImageView (frame:  CGRect (x: 2* self .scrollerViewWidth!, y: 0,
                     width:  self .scrollerViewWidth!, height:  self .scrollerViewHeight!));
         self .scrollerView?.showsHorizontalScrollIndicator =  false
         
         //设置初始时左中右三个imageView的图片(分别时数据源中最后一张,第一张,第二张图片)
         if ( self .dataSource?.count != 0){
             resetImageViewSource()
         }
         
         self .scrollerView?.addSubview( self .leftImageView!)
         self .scrollerView?.addSubview( self .middleImageView!)
         self .scrollerView?.addSubview( self .rightImageView!)
     }
     
     //设置页控制器
     func  configurePageController() {
         self .pageControl =  UIPageControl (frame:  CGRect (x: kScreenWidth/2-60,
                         y:  self .scrollerViewHeight! - 20, width: 120, height: 20))
         self .pageControl?.numberOfPages = ( self .dataSource?.count)!
         self .pageControl?.isUserInteractionEnabled =  false
         self .view.addSubview( self .pageControl!)
     }
     
     //设置自动滚动计时器
     func  configureAutoScrollTimer() {
         //设置一个定时器,每三秒钟滚动一次
         autoScrollTimer =  Timer .scheduledTimer(timeInterval: 3, target:  self ,
                     selector: #selector( SliderGalleryController .letItScroll),
                     userInfo:  nil , repeats:  true )
     }
     
     //计时器时间一到,滚动一张图片
     func  letItScroll(){
         let  offset =  CGPoint (x: 2*scrollerViewWidth!, y: 0)
         self .scrollerView?.setContentOffset(offset, animated:  true )
     }
     
     //每当滚动后重新设置各个imageView的图片
     func  resetImageViewSource() {
         //当前显示的是第一张图片
         if  self .currentIndex == 0 {
             self .leftImageView?.imageFromURL( self .dataSource!.last!,
                                              placeholder: placeholderImage)
             self .middleImageView?.imageFromURL( self .dataSource!.first!,
                                                placeholder: placeholderImage)
             let  rightImageIndex = ( self .dataSource?.count)!>1 ? 1 : 0  //保护
             self .rightImageView?.imageFromURL( self .dataSource![rightImageIndex],
                                               placeholder: placeholderImage)
         }
         //当前显示的是最好一张图片
         else  if  self .currentIndex == ( self .dataSource?.count)! - 1 {
             self .leftImageView?.imageFromURL( self .dataSource![ self .currentIndex-1],
                                              placeholder: placeholderImage)
             self .middleImageView?.imageFromURL( self .dataSource!.last!,
                                                placeholder: placeholderImage)
             self .rightImageView?.imageFromURL( self .dataSource!.first!,
                                               placeholder: placeholderImage)
         }
         //其他情况
         else {
             self .leftImageView?.imageFromURL( self .dataSource![ self .currentIndex-1],
                                              placeholder: placeholderImage)
             self .middleImageView?.imageFromURL( self .dataSource![ self .currentIndex],
                                                placeholder: placeholderImage)
             self .rightImageView?.imageFromURL( self .dataSource![ self .currentIndex+1],
                                               placeholder: placeholderImage)
         }
     }
     
     //scrollView滚动完毕后触发
     func  scrollViewDidScroll(_ scrollView:  UIScrollView ) {
         //获取当前偏移量
         let  offset = scrollView.contentOffset.x
         
         if ( self .dataSource?.count != 0){
             
             //如果向左滑动(显示下一张)
             if (offset >=  self .scrollerViewWidth!*2){
                 //还原偏移量
                 scrollView.contentOffset =  CGPoint (x:  self .scrollerViewWidth!, y: 0)
                 //视图索引+1
                 self .currentIndex =  self .currentIndex + 1
                 
                 if  self .currentIndex ==  self .dataSource?.count {
                     self .currentIndex = 0
                 }
             }
         
             //如果向右滑动(显示上一张)
             if (offset <= 0){
                 //还原偏移量
                 scrollView.contentOffset =  CGPoint (x:  self .scrollerViewWidth!, y: 0)
                 //视图索引-1
                 self .currentIndex =  self .currentIndex - 1
                 
                 if  self .currentIndex == -1 {
                     self .currentIndex = ( self .dataSource?.count)! - 1
                 }
             }
             
             //重新设置各个imageView的图片
             resetImageViewSource()
             //设置页控制器当前页码
             self .pageControl?.currentPage =  self .currentIndex
         }
     }
     
     //手动拖拽滚动开始
     func  scrollViewWillBeginDragging(_ scrollView:  UIScrollView ) {
         //使自动滚动计时器失效(防止用户手动移动图片的时候这边也在自动滚动)
         autoScrollTimer?.invalidate()
     }
     
     //手动拖拽滚动结束
     func  scrollViewDidEndDragging(_ scrollView:  UIScrollView ,
                                   willDecelerate decelerate:  Bool ) {
         //重新启动自动滚动计时器
         configureAutoScrollTimer()
         
     }
     
     override  func  didReceiveMemoryWarning() {
         super .didReceiveMemoryWarning()
     }
}

5,使用样例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import  UIKit
 
class  ViewController UIViewController SliderGalleryControllerDelegate  {
     
     //获取屏幕宽度
     let  screenWidth =   UIScreen .main.bounds.size.width
     
     //图片轮播组件
     var  sliderGallery :  SliderGalleryController !
     
     
     override  func  viewDidLoad() {
         super .viewDidLoad()
         
         //初始化图片轮播组件
         sliderGallery =  SliderGalleryController ()
         sliderGallery.delegate =  self
         sliderGallery.view.frame =  CGRect (x: 10, y: 40, width: screenWidth-20,
                                           height: (screenWidth-20)/4*3);
         
         //将图片轮播组件添加到当前视图
         self .addChildViewController(sliderGallery)
         self .view.addSubview(sliderGallery.view)
         
         //添加组件的点击事件
         let  tap =  UITapGestureRecognizer (target:  self ,
                         action: #selector( ViewController .handleTapAction(_:)))
         sliderGallery.view.addGestureRecognizer(tap)
     }
     
     //图片轮播组件协议方法:获取内部scrollView尺寸
     func  galleryScrollerViewSize() ->  CGSize  {
         return  CGSize (width: screenWidth-20, height: (screenWidth-20)/4*3)
     }
     
     //图片轮播组件协议方法:获取数据集合
     func  galleryDataSource() -> [ String ] {
                 "http://tupian.enterdesk.com/2012/1015/zyz/03/5.jpg" ,
     }
 
     //点击事件响应
     func  handleTapAction(_ tap: UITapGestureRecognizer )-> Void {
         //获取图片索引值
         let  index = sliderGallery.currentIndex
         //弹出索引信息
         let  alertController =  UIAlertController (title:  "您点击的图片索引是:" ,
                                                 message:  "\(index)" , preferredStyle: .alert)
         let  cancelAction =  UIAlertAction (title:  "确定" , style: .cancel, handler:  nil )
         alertController.addAction(cancelAction)
         self .present(alertController, animated:  true , completion:  nil )
     }
     
     override  func  didReceiveMemoryWarning() {
         super .didReceiveMemoryWarning()
     }
}
源码下载 hangge_1314.zip
原文出自: www.hangge.com   转载请保留原文链接: http://www.hangge.com/blog/cache/detail_1314.html
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值