田腾飞的博客

【iOS开发】两种方式完美实现无限图片轮播(Swift3)

自从找到工作以来一直都是搞逻辑层,UI层的实现基本不用我搞,所以UI层的东西俺研究的不是特别多,然而像俺这种追求完美的男子,俺是不允许这种偏科的情况出现滴,所以2017年计划将一部分时间花费在UI层的研究上。那么先从最简单的图片轮播搞起吧,给自己一个完美的开端(说了那么多,其实根本原因是我最近没有啥写的了🤣)!

图片轮播网上一搜一大堆,做法也是多种多样,不过目的都是能搞定的。这篇文章主要总结了一下两种最完美的实现方式。

  1. 使用UIScrollView实现
  2. 使用UICollectionView实现

虽然这两种实现方式有点小区别,但都能做到内存消耗很少,实现imageView的复用,实现无限图片轮播效果。先看下效果(图片有点大,让网页多加载一会):

效果图

Demo地址猛戳我 使用的是Swift 3编写。

好了,其实实现原理看代码就行了,不需要再往下写了。但是像俺这种追求完美的男子,不允许文章就这么短,俺接着往下写,小伙伴们可以直接去看代码了,不要打扰我装逼!🤒

UIScrollView实现原理

使用UIScrollView实现的原理超级简单,你懂,就是很简单。我们用三个UIImageView循环去显示图片,这样子内存占用得到了保障,效果也非常好。具体做法:

  1. 准备好一个UIScrollView,上面依次放上去三个UIImageView,简称为A,B,C。
  2. 假设我们要放4张图片,那么首先我们在A B C上依次放的是:A -> 最后一张图片, B -> 第一张图片, C -> 第二张图片。首先让ScrollView显示B也就是第一张图片。
1
2
3
4
5
6
/// 只使用3个UIImageView,依次设置好最后一个,第一个,第二个图片,这里面使用取模运算。
for index in 0..<3 {
let imageView = UIImageView(frame: CGRect(x: CGFloat(index) * kScreenWidth, y: 0, width: kScreenWidth, height: kScreenHeight))
imageView.image = UIImage(named: "\((index + 3) % 4).png")
scrollView.addSubview(imageView)
}
  • 当我们左滑显示第二张图片也就是C,当页面显示滑动停止以后,我们将A B C重新显示图片为:A -> 第一张图片, B -> 第二张图片, C -> 第三张图片,然后让ScrollView再次显示B。所以界面显示的图片虽然变了,但一直显示的还是中间那个UIImageView。这样就造成了无限循环滑动。右滑原理一样。

  • 如果我们右滑显示最后一张图片也就是A,当页面显示滑动停止以后,我们将A B C重新显示图片为:A -> 倒数第二张图片, B -> 最后一张图片, C -> 第一张图片,然后让ScrollView再次显示B。这样子就是一个无限循环轮播。

也就是说scrollView永远显示就是中间那个imageView,只是显示的图片不一样,所以左滑右滑都会有图片,就是传说中的无限滚动。关键点就是图片显示以后有一个reloadImage的过程。(为了简单我使用了万恶的 !

1
2
3
4
5
6
7
8
9
10
/// 重新加载图片,重新设置3个imageView
func reloadImage() {
let currentIndex = pageView.currentPage
let nextIndex = (currentIndex + 1) % 4
let preIndex = (currentIndex + 3) % 4
(scrollView.subviews[0] as! UIImageView).image = UIImage(named: "\(preIndex).png")
(scrollView.subviews[1] as! UIImageView).image = UIImage(named: "\(currentIndex).png")
(scrollView.subviews[2] as! UIImageView).image = UIImage(named: "\(nextIndex).png")
}

至于自动滚动就是添加NSTimer,具体可以参考一下Demo

UICollectionView原理

使用UICollectionView的原理和使用UIScrollView的原理有点区别。具体哪种方式好就是仁者见仁智者见智了。使用UICollectionView的原理是设置2倍图片数量的Cell,循环显示图片,具体做法:

  1. 设置UICollectionView的cell为两倍image数量,然后循环对cell从第一张图片到最后一张图片赋值,首先显示第二部分的第一张图片。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count * 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? BannerCollectionViewCell
if let cell = cell {
cell.imageName = images[indexPath.item % 4]
return cell
}
return cell!
}
  • 当左滑显示到第二部分的最后一张图片的时候,也就是最后一个cell,当图片显示完成以后,我们将scrollView设置为显示第一部分的最后一张图片,这样子就可以继续右滑,就是无限循环轮播的效果。
  • 当右滑显示到第一部分的第一张图片的时候,也就是第一个cell,当图片显示完成以后,我们将scrollView设置为显示第二部分的第一张图片,这样子就可以继续左滑,就是无限循环轮播的效果。

关键方法还是reloadImage方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func reloadImage() {
guard let currentIndexPath = currentIndexPath else {
return
}
if currentIndexPath.item == images.count * 2 - 1 { //如果是最后一个图片,回到第一部分的最后一张图片
let newIndexPath = IndexPath(item: images.count - 1, section: 0)
self.currentIndexPath = newIndexPath
collectionView.scrollToItem(at: newIndexPath, at: .centeredHorizontally, animated: false)
} else if currentIndexPath.item == 0 { //如果是第一个图片,就回到第二部分的第一张图片
let newIndexPath = IndexPath(item: images.count, section: 0)
self.currentIndexPath = newIndexPath
collectionView.scrollToItem(at: newIndexPath, at: .centeredHorizontally, animated: false)
}
}

哈哈,是不是炒鸡简单,具体代码小伙伴们直接参考Demo,代码稍作修改就可以进行复用了。🤒

小伙伴们如果感觉文章可以,可以关注博主博客

小伙伴们多多关注博主微博,探索博主内心世界😁

如要转载请注明出处。

热评文章