轮播图

"迈入Swift的学习中"

Posted by 李勇 on 2017-07-23

利用闲暇时间写了一个banner

原理

scrollview中添加3张图片,每次都是显示中间那张图片,当滚动或者按照时间轮播的时候显示后一张的同时将后一张图片放在中间并且scrollview显示中间图片,并重置两边的图片

##问题
现在用手滚动的时候效果还算满意,但是根据定时器轮播的时候图片总是闪换,无法达到手动滑动的那种顺畅感觉,如果有好的方法请联系我,感谢!

##效果
支持横向轮播和纵向轮播
使用方法,可设置imgUrlArray图片地址数组,customerTitleArray仅显示title,customerImgArray图片数组,也可设置pagecontrol的颜色以及是否隐藏
image
image

##使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//横向轮播
lazy var bannerView1 : LYBannerView = {
let bannerView = LYBannerView(frame: CGRect(x: 0, y: 0, width: kScreenW, height: kScreenW * 320 / 750), isHorizontalScroll: true, delegate: self)
bannerView.backgroundColor = UIColor.white
bannerView.currentColor = UIColor.blue
bannerView.normalColor = UIColor.green
bannerView.showPageControl = true
bannerView.tag = 2112
self.headerView.addSubview(bannerView)
return bannerView
}()
//纵向轮播
lazy var bannerView2 : LYBannerView = {
let bannerView = LYBannerView(frame: CGRect(x: 80, y: 0, width: kScreenW - 80 - 60, height: 49), isHorizontalScroll: false, delegate: self)
bannerView.showPageControl = false
bannerView.backgroundColor = UIColor.white
bannerView.tag = 2222
self.recommendView.addSubview(bannerView)
return bannerView
}()
//设置图片url或者显示的title
self.bannerView1.imgUrlArray = bannerArray3
self.bannerView2.customerTitleArray = bannerArray4

##源码

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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
//
// LYBannerView.swift
// qixiaofu
// _
// | | /\ /\
// | | \ \_/ /
// | | \_~_/
// | | / \
// | |__/\ [ ]
// |_|__,/ \_/
//
// Created by ly on 2017/6/15.
// Copyright © 2017年 qixiaofu. All rights reserved.
//
import UIKit
@objc
protocol LYBannerViewDelegate : NSObjectProtocol {
@objc func lyBannerClick(lyBanner:LYBannerView, index : Int)
}
class LYBannerView: UIView {
var delegate : LYBannerViewDelegate?
var currentColor : UIColor{//当前page的颜色
didSet{
self.pageControl.currentPageIndicatorTintColor = currentColor
}
}
var normalColor : UIColor{//其他page的颜色
didSet{
self.pageControl.pageIndicatorTintColor = normalColor
}
}
var showPageControl : Bool{//是否显示页码控制器
didSet{
if !showPageControl {
self.pageControl.isHidden = true
}
}
}
var customerImgArray : Array<UIImage>{//显示的图片后期赋值
didSet{
self.imgArray = customerImgArray
self.setUpSubviews()
}
}
var customerTitleArray : Array<String>{//显示的标题后期赋值
didSet{
self.imgArray = self.convertStringArrayToImageArray(stringArray: customerTitleArray)
self.setUpSubviews()
}
}
var imgUrlArray : Array<String>{//显示图片的地址后期赋值
didSet{
self.isUrl = true
self.setUpSubviews()
}
}
fileprivate var isUrl : Bool//是否通过url加载图片
fileprivate let isHorizontalScroll : Bool//是否为横向滚动
fileprivate var imgArray : Array<UIImage>//显示的图片
fileprivate let scrollView = UIScrollView()//
fileprivate let pageControl = UIPageControl()//
fileprivate var timer = Timer()//
fileprivate var imgIndex : Int//当前显示的图片的索引
fileprivate var isAutoScrolling : Bool//是否为自动滚动状态
fileprivate let imgV1 = UIImageView()//
fileprivate let imgV2 = UIImageView()//
fileprivate let imgV3 = UIImageView()//
init(frame: CGRect, imgArray: Array<UIImage>, isHorizontalScroll: Bool, delegate: LYBannerViewDelegate) {
self.imgArray = imgArray
self.isHorizontalScroll = isHorizontalScroll
self.delegate = delegate
self.currentColor = UIColor.red
self.normalColor = UIColor.white
self.showPageControl = true
self.imgIndex = 0
self.isAutoScrolling = true
self.customerTitleArray = Array()
self.customerImgArray = Array()
self.imgUrlArray = Array()
self.isUrl = false
super.init(frame:frame)
self.frame = frame
self.setUpSubviews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(frame: CGRect, titleArray: Array<String>, isHorizontalScroll: Bool, delegate: LYBannerViewDelegate) {
self.imgArray = Array()
self.isHorizontalScroll = isHorizontalScroll
self.delegate = delegate
self.currentColor = UIColor.red
self.normalColor = UIColor.white
self.showPageControl = true
self.imgIndex = 0
self.isAutoScrolling = true
self.customerTitleArray = Array()
self.customerImgArray = Array()
self.imgUrlArray = Array()
self.isUrl = false
super.init(frame:frame)
self.frame = frame
self.imgArray = self.convertStringArrayToImageArray(stringArray: titleArray)
self.setUpSubviews()
}
init(frame: CGRect, isHorizontalScroll: Bool, delegate: LYBannerViewDelegate) {
self.isHorizontalScroll = isHorizontalScroll
self.delegate = delegate
self.currentColor = UIColor.red
self.normalColor = UIColor.white
self.showPageControl = true
self.imgIndex = 0
self.isAutoScrolling = true
self.imgArray = Array()
self.customerTitleArray = Array()
self.customerImgArray = Array()
self.imgUrlArray = Array()
self.isUrl = false
super.init(frame:frame)
self.frame = frame
self.setUpSubviews()
}
}
extension LYBannerView{
func setUpSubviews() {
self.imgIndex = 0
if self.isUrl{
//1.图片至少为2张
if self.imgUrlArray.count == 0{
let imgUrl = "http://www.7xiaofu.com/UPLOAD/sys/2017-03-07/~UPLOAD~sys~2017-03-07@1488850751.jpg"
self.imgUrlArray.insert(imgUrl, at: 0)
self.imgUrlArray.insert(imgUrl, at: 1)
self.scrollView.isScrollEnabled = false
}else if self.imgUrlArray.count == 1{
self.imgUrlArray.insert(self.imgUrlArray[0], at: 1)
self.scrollView.isScrollEnabled = false
}else{
self.scrollView.isScrollEnabled = true
//4.定时器
self.setUpTimer()
}
}else{
//1.图片至少为2张
if self.imgArray.count == 0{
let img = UIImage()
self.imgArray.insert(img, at: 0)
self.imgArray.insert(img, at: 1)
self.scrollView.isScrollEnabled = false
}else if self.imgArray.count == 1{
self.imgArray.insert(self.imgArray[0], at: 1)
self.scrollView.isScrollEnabled = false
}else{
self.scrollView.isScrollEnabled = true
//4.定时器
self.setUpTimer()
}
}
//2.设置scroll
self.setUpScrollView()
//3.pagecontrol
self.setUpPageControl()
}
/**
通过三个imageview,每次滚动或者手动滑动后都重新设置imageview的图片,并且保证scrollview显示的是中间的imageview
*/
func setUpScrollView() {
self.scrollView.frame = self.bounds
self.scrollView.backgroundColor = UIColor.clear
if self.isHorizontalScroll{
self.scrollView.contentSize = CGSize(width: self.frame.width * 3, height: self.frame.height)
}else{
self.scrollView.contentSize = CGSize(width: self.frame.width, height: self.frame.height * 3)
}
self.scrollView.delegate = self
self.scrollView.isPagingEnabled = true
self.scrollView.showsVerticalScrollIndicator = false
self.scrollView.showsHorizontalScrollIndicator = false
self.scrollView.bounces = false
self.addSubview(self.scrollView)
var orginX : CGFloat
var orginY : CGFloat
if self.isHorizontalScroll{
orginX = self.frame.width
orginY = 0
}else{
orginX = 0
orginY = self.frame.height
}
self.imgV1.frame = CGRect(x:0, y:0, width:self.frame.width, height:self.frame.height)
self.imgV1.backgroundColor = UIColor.clear
self.imgV1.contentMode = .scaleAspectFit
self.imgV1.addTapAction(action: #selector(LYBannerView.imageViewClickAction), target: self)
self.imgV2.frame = CGRect(x:orginX, y:orginY, width:self.frame.width, height:self.frame.height)
self.imgV2.backgroundColor = UIColor.clear
self.imgV2.contentMode = .scaleAspectFit
self.imgV2.addTapAction(action: #selector(LYBannerView.imageViewClickAction), target: self)
self.imgV3.frame = CGRect(x:orginX * 2, y:orginY * 2, width:self.frame.width, height:self.frame.height)
self.imgV3.backgroundColor = UIColor.clear
self.imgV3.contentMode = .scaleAspectFit
self.imgV3.addTapAction(action: #selector(LYBannerView.imageViewClickAction), target: self)
self.scrollView.addSubview(self.imgV1)
self.scrollView.addSubview(self.imgV2)
self.scrollView.addSubview(self.imgV3)
self.reSetUpImageViewOfScrollView()
}
/**重新排布ScrollView中的ImageView*/
func reSetUpImageViewOfScrollView() {
if self.isUrl{
if self.imgIndex >= self.imgUrlArray.count{
self.imgIndex = 0
}else if self.imgIndex < 0{
self.imgIndex = self.imgUrlArray.count - 1
}
self.pageControl.currentPage = self.imgIndex
self.imgV2.kf.setImage(with: URL(string:self.imgUrlArray[self.imgIndex]),placeholder:#imageLiteral(resourceName: "banner1"))
if self.imgIndex == 0{
self.imgV1.kf.setImage(with: URL(string:self.imgUrlArray[self.imgUrlArray.count - 1]),placeholder:#imageLiteral(resourceName: "banner1"))
self.imgV3.kf.setImage(with: URL(string:self.imgUrlArray[self.imgIndex + 1]),placeholder:#imageLiteral(resourceName: "banner1"))
}else if self.imgIndex == self.imgUrlArray.count - 1{
self.imgV1.kf.setImage(with: URL(string:self.imgUrlArray[self.imgIndex - 1]),placeholder:#imageLiteral(resourceName: "banner1"))
self.imgV3.kf.setImage(with: URL(string:self.imgUrlArray[0]))
}else{
self.imgV1.kf.setImage(with: URL(string:self.imgUrlArray[self.imgIndex - 1]),placeholder:#imageLiteral(resourceName: "banner1"))
self.imgV3.kf.setImage(with: URL(string:self.imgUrlArray[self.imgIndex + 1]),placeholder:#imageLiteral(resourceName: "banner1"))
}
if self.isHorizontalScroll{
self.scrollView.setContentOffset(CGPoint(x:self.frame.width, y:0), animated: false)
}else{
self.scrollView.setContentOffset(CGPoint(x:0, y:self.frame.height), animated: false)
}
}else{
if self.imgIndex >= self.imgArray.count{
self.imgIndex = 0
}else if self.imgIndex < 0{
self.imgIndex = self.imgArray.count - 1
}
self.pageControl.currentPage = self.imgIndex
self.imgV2.image = self.imgArray[self.imgIndex]
if self.imgIndex == 0{
self.imgV1.image = self.imgArray[self.imgArray.count - 1];
self.imgV3.image = self.imgArray[self.imgIndex + 1]
}else if self.imgIndex == self.imgArray.count - 1{
self.imgV1.image = self.imgArray[self.imgIndex - 1];
self.imgV3.image = self.imgArray[0]
}else{
self.imgV1.image = self.imgArray[self.imgIndex - 1];
self.imgV3.image = self.imgArray[self.imgIndex + 1]
}
if self.isHorizontalScroll{
self.scrollView.setContentOffset(CGPoint(x:self.frame.width, y:0), animated: false)
}else{
self.scrollView.setContentOffset(CGPoint(x:0, y:self.frame.height), animated: false)
}
}
}
/**pagecontrol*/
func setUpPageControl() {
if !self.showPageControl{
return
}
self.pageControl.frame = CGRect(x:0, y:self.frame.height - 20, width:self.frame.width, height:20)
self.pageControl.backgroundColor = UIColor.clear
self.pageControl.numberOfPages = self.isUrl ? self.imgUrlArray.count : self.imgArray.count
self.pageControl.currentPageIndicatorTintColor = self.currentColor
self.pageControl.pageIndicatorTintColor = self.normalColor
self.pageControl.currentPage = 0
self.pageControl.hidesForSinglePage = true
self.addSubview(self.pageControl)
}
//设置定时器
func setUpTimer() {
if self.timer.isValid{
self.timer.invalidate()
}
self.timer = Timer(timeInterval: 2.0, target: self, selector: #selector(LYBannerView.changeImage), userInfo: nil, repeats: true)
RunLoop.main.add(self.timer, forMode: .defaultRunLoopMode)
timer.fire()
self.isAutoScrolling = true
}
@objc func changeImage(){
if isAutoScrolling {
self.imgIndex += 1
if self.isHorizontalScroll {
self.scrollView.setContentOffset(CGPoint(x:self.frame.width * 2, y:0), animated: true)
}else{
self.scrollView.setContentOffset(CGPoint(x:0, y:self.frame.height * 2), animated: true)
}
self.reSetUpImageViewOfScrollView()
}
}
}
extension LYBannerView : UIScrollViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.timer.invalidate()
self.isAutoScrolling = false
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
}
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var showIndex : CGFloat
if self.isHorizontalScroll{
showIndex = scrollView.contentOffset.x / self.frame.width
}else{
showIndex = scrollView.contentOffset.y / self.frame.height
}
if showIndex == 0{
//当前显示的第一个imgv
self.imgIndex -= 1
self.reSetUpImageViewOfScrollView()
}else if showIndex == 1{
//当前显示的第二个imgv
}else if showIndex == 2{
//当前显示的第三个imgv
self.imgIndex += 1
self.reSetUpImageViewOfScrollView()
}
self.setUpTimer()
}
}
extension LYBannerView{
//图片点击事件处理
func imageViewClickAction() {
self.delegate?.lyBannerClick(lyBanner:self, index: self.imgIndex)
}
}
//显示滚动文字
extension LYBannerView{
func convertStringArrayToImageArray(stringArray:Array<String>) -> Array<UIImage> {
let arrM = NSMutableArray()
for s in stringArray{
let lbl = UILabel(frame:self.bounds)
lbl.text = s
lbl.font = UIFont.systemFont(ofSize: 14.0)
lbl.textAlignment = .center
let image = self.converViewToImage(v: lbl)
arrM.add(image)
}
return arrM as! Array<UIImage>
}
//label转image
func converViewToImage(v:UIView) -> UIImage {
let s = v.bounds.size
// 下面方法,第一个参数表示区域大小。第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传false,否则传true。第三个参数就是屏幕密度了
UIGraphicsBeginImageContextWithOptions(s, false, UIScreen.main.scale)
v.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}