forked from jiandanxinli/jiandanxinli.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2016-07-29.html
156 lines (133 loc) · 10.5 KB
/
2016-07-29.html
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
<!DOCTYPE html><html lang="zh-CN"><head><meta content="IE=edge;chrome=1" http-equiv="X-UA-Compatible" /><meta content="width=device-width, initial-scale=1" name="viewport" /><title>iOS上简易轮播图的实现 · 简单心理技术团队</title><meta content="以一个三张imageView的轮播图为例,具体到如何实现轮播图,添加自动轮播器,添加手势点击事件等。" name="description" /><link href="/stylesheets/app.css" rel="stylesheet" /><link rel="alternate" type="application/atom+xml" title="Atom Feed" href="/feed.xml" /><link href="/images/favicon.ico" rel="icon" /></head><body><div class="animated fadeInDown"><div class="header container"><a class="logo" href="/"><img src="/images/logo.png" alt="Logo" /></a><h1><a href="/">简单心理 · 技术团队</a></h1><a class="github" href="https://github.com/jiandanxinli">github.com/jiandanxinli</a></div></div><div class="animated_container"><div class="content container animated fadeIn delay"><h2>iOS上简易轮播图的实现</h2><div class="meta"><span class="date">2016-07-29</span><span class="author">Qiuncheng</span></div><blockquote>以一个三张imageView的轮播图为例,具体到如何实现轮播图,添加自动轮播器,添加手势点击事件等。</blockquote><h3>前言</h3>
<p>见过很多的iOS应用,都有无限轮播图,之前也看到过很多相关实现的文章,可是仅仅就是一看而过罢了。当自己在项目中用到这个,真正去写的时候才发现不是很容易,遇到了一些问题,这篇文章就记录下自己最后成功实现轮播图的历程。</p>
<h3>原理</h3>
<p>原理其实就是一种假象。不过在我这里,目前有过两种原理的实现。一种利用<code>UICollectionView</code>实现轮播,另一种利用<code>UIScrollView</code>实现轮播。
今天我们要来打造一款这样的轮播图(图画的不好,请勿见怪)。</p>
<p><img src="https://cloud.githubusercontent.com/assets/9990834/17270175/36fa47a0-568f-11e6-8f3f-bbed783d6b41.png" alt="举例:三张图的无限轮播" /></p>
<h4>原理一:利用<code>UIScrollView</code>实现轮播图。</h4>
<p>要想实现这样的效果,我们使用<code>UIScrollView</code>包含image0,image1,image2的三个<code>UIImageView</code>都是放在<code>UIScrollView</code>里面的,但是这样的话是不可以实现轮播的。要想实现轮播就要再在该<code>UIScrollView</code>的左右两侧各加一张<code>UIImageView</code>。在最后一张放image0, 第一张放image2。这样的话当我们滚动到最后或者最前面的的时候,我们就把列表切换到相应的位置,注意这时候切换的时候不能有动画。只需要调用<code>scrollView.contentOffset = CGPoint(...)</code>即可。</p>
<p><img src="https://cloud.githubusercontent.com/assets/9990834/17270176/408925d4-568f-11e6-9217-e26c3cf09093.png" alt="实际UISrollView图" /></p>
<h4>原理二:利用<code>UICollectionView</code>实现轮播图。</h4>
<p>你当然可以利用<strong>原理一</strong>再用<code>UICollectionView</code>实现一次。但是我这里采用一种偷懒的方式,利用<code>UICollectionView</code>的cell重用机制。创建个无数个cell,比如3x20000。当用户第一次进来的我们就将UICollectionView滑到3x20000x0.5的位置。然后利用<code>cell.indexPath.item % 3</code>来对cell上的UIImageView进行image显示。这种方式比较偷懒,在后来添加NSTimer自动轮播和点击事件的时候也比较简单,不过有点大炮打小鸟的感觉。所以我在这里也只是介绍下原理,如果你有兴趣,可以自己尝试去实现下。而且UICollectionView自带一个方法<code>- scrollToItemAtIndexPath:atScrollPosition:animated:</code>还比较厉害。</p>
<h3>具体实现</h3>
<p>针对原理一,我就来简单实现下。(我这里使用代码创建,你也可以使用Storyboard创建,原理一样)</p>
<h4>创建工程,创建<code>BannerView.Swift</code>,添加初始化代码如下:</h4>
<pre class="highlight plaintext"><code>/// 初始化scrollView
lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.delegate = self
scrollView.alwaysBounceVertical = false
scrollView.bounces = true
scrollView.pagingEnabled = true
scrollView.scrollEnabled = true
scrollView.showsVerticalScrollIndicator = false
scrollView.showsHorizontalScrollIndicator = false
return scrollView
}()
/// 初始化pageControl
lazy var pageControl: UIPageControl = {
let pageControl = UIPageControl()
pageControl.currentPageIndicatorTintColor = UIColor.redColor()
pageControl.pageIndicatorTintColor = UIColor.whiteColor()
return pageControl
}()
/// 在init里调用setupSubviews即可
func setupSubviews() {
self.addSubview(scrollView)
self.addSubview(pageControl)
scrollView.translatesAutoresizingMaskIntoConstraints = false
pageControl.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[v]|", options: [], metrics: nil, views: ["v": scrollView]))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[v]|", options: [], metrics: nil, views: ["v": scrollView]))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[p(==20)]-10-|", options: [], metrics: nil, views: ["p": pageControl]))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[p(==100)]-10-|", options: [], metrics: nil, views: ["p": pageControl]))
}
</code></pre>
<h4>初始化UIScrollView:</h4>
<pre class="highlight plaintext"><code>func setupScrollView() {
/// 创建 (imageNames.count + 2)个UIImageView
for index in 0 ... (imageNmaes.count + 1) {
let imageView = UIImageView(frame: CGRect(x: self.width*CGFloat(index), y: 0, width: self.width, height: self.height))
var picName = String()
switch index {
case 0:
picName = imageNames[imageNames.count-1]
break
case imageNames.count + 1:
picName = imageNames[0]
break
default:
picName = imageNames[index-1]
break
}
// imageView.af_setImageWithURL(NSURL(string: picName)!)
imageView.image = UIImage(named: picName)
imageView.contentMode = .ScaleToFill
imageView.clipsToBounds = true
imageView.userInteractionEnabled = true
scrollView.addSubview(imageView)
}
scrollView.contentSize = CGSize(width: self.width * CGFloat(imageNames.count + 2), height: self.height)
scrollView.contentOffset = CGPoint(x: self.width, y: 0)
}
</code></pre>
<h4>无限轮番的实现。(重点)使用UIScrollViewDelegate协议。</h4>
<pre class="highlight plaintext"><code>func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView == self.scrollView {
let contentOffsetX = scrollView.contentOffset.x
///向前滑动到第0张图的时候,滚到第三张图
if contentOffsetX == 0 {
scrollView.contentOffset = CGPoint(x: self.width * CGFloat(self.imageNames.count), y: 0)
}
/// 跑到第三张图的时候,滚到第0张图
if contentOffsetX == CGFloat(self.imageNames.count + 1)*self.width {
scrollView.contentOffset = CGPoint(x: self.width, y: 0)
}
/// 改变pageControl,这里要注意,一定要一定要一定要 - 0.5, 因为最前面的第0张图一直不显示。
let index = scrollView.contentOffset.x / self.width - 0.5
self.pageControl.currentPage = Int(index)
}
}
</code></pre>
<h4>添加计时器</h4>
<p>好了,做到这里,你已经成功实现了轮播图,可是这个轮播图是手动的,下面添加自动滚动。也很简单,设置一个NSTimer计时器即可。代码如下:</p>
<pre class="highlight plaintext"><code>// MARK: - Timer
var timer: NSTimer?
var i = 1
/// 在scrollView上的图片成功设置后调用startTimer即可
private func startTimer() {
if timer != nil {
self.stopTimer()
}
/// 这里设置的滚动间隔为2秒
timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: #selector(autoScroll), userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(timer!, forMode: NSDefaultRunLoopMode)
}
private func stopTimer() {
timer?.invalidate()
timer = nil
}
func autoScroll() {
if i == imageNames.count + 1 {
i = 1
}
i += 1
/// 在处理无限轮番的时候设置contentOffset没有添加animated,这里要添加上来,不然有种很突兀的感觉。
scrollView.setContentOffset(CGPoint(x: self.width * CGFloat(i), y: 0), animated: true)
}
/// 手动滚动结束后恢复计时
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
self.startTimer()
}
/// 当手动滚动开始时停止计时
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
self.stopTimer()
}
</code></pre>
<h4>添加具体点击事件</h4>
<p>具体到点击事件的话,我是放在初始化imageView那里处理的,给imageVIew添加一个UITapGestureRecognizer,在这里最好再写一个代理方法,将imageView的点击事件传递出去。然后根据当前<code>contentOffet.x / self.width</code>来将具体哪张图片的事件传递出去。我就不用代码展示了。</p>
<h3>结尾</h3>
<p>还是比较简单的。但是我这个复用性比较差,封装的也不好,可是具体要看思路😂。代码实现放在了Github Wiki上了<a href="https://github.com/qiuncheng/qiuncheng.github.io/wiki/BannerView.Swift">BannerView.Swift</a>,由于工程量太小,就没将工程文件上传了。</p>
<h4>关于作者</h4>
<p><a href="http://qiuncheng.com">Qiuncheng</a>,一位正在iOS路上前行的初学者,正在努力成为一名合格的iOS开发者。</p>
</div></div><a class="top" href="#">Back to Top</a><div class="footer"><div class="container"><a class="logo" href="https://www.jiandanxinli.com"><img src="/images/logo_text.png" alt="简单心理" /></a><div class="links"><a href="/">Home</a><a href="/feed.xml">Feed</a><a href="https://github.com/jiandanxinli">Github</a><a href="https://www.jiandanxinli.com/pages/37">About</a></div><p>© 2014 - 2016 北京竹间科技有限公司 版权所有</p></div></div></body></html>