转载

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

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

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

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

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

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

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

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

UIScrollView实现原理

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

  1. 准备好一个UIScrollView,上面依次放上去三个UIImageView,简称为A,B,C。
  2. 假设我们要放4张图片,那么首先我们在A B C上依次放的是: A -> 最后一张图片 , B -> 第一张图片 , C -> 第二张图片 。首先让ScrollView显示B也就是第一张图片。
/// 只使用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的过程。(为了简单我使用了万恶的 !

/// 重新加载图片,重新设置3个imageView
funcreloadImage() {
    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从第一张图片到最后一张图片赋值,首先显示第二部分的第一张图片。
funcnumberOfSections(incollectionView: UICollectionView) -> Int {
    return 1
}
    
funccollectionView(_collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return images.count * 2
}
    
funccollectionView(_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方法

funcreloadImage() {
    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,代码稍作修改就可以进行复用了。裸

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

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

如要转载请注明出处。

原文  http://www.codertian.com/2017/01/07/ui-image-cycle-banner/
正文到此结束
Loading...