今天公司里的实习生跑过来问我一般App上广告的无限滚动是怎么实现的,刚好很久没写博客了,就决定写下了,尽量帮助那些处于刚学iOS的程序猿.

做一个小demo,大概实现效果如下图所示:

基本实现思路:

1. 在你需要放置无限滚动展示数据的地方把他的数据,在原本的基础上把你要展示的数据扩大三倍.(当然扩大两倍也是可以的,三倍的话,比较好演示)

   // MARK: - 设置数据源
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// print(self.arrayM.count)
return self.arrayM.count *
}

2.当在定时器的作用下,或者在拖动情况存下滚动到第八个时候,设置此时的collectionView.contentOffset.x等于滚动到第三个cell的contentOffset.x

if collectionView.contentOffset.x == CGFloat( * self.arrayM.count - ) * self.collectionView.bounds.width {
self.collectionView.contentOffset.x = CGFloat(self.arrayM.count - ) * self.collectionView.bounds.width
}

3.当拖动到第0个cell时,设置此时的collectionView.contentOffset.x等于第六个cell的contentOffset.x

if collectionView.contentOffset.x ==  {
self.collectionView.contentOffset.x = CGFloat( * self.arrayM.count - ) * self.collectionView.bounds.width }

代码如下:

我在代码中用到5张照片,所以应该一共有15个cell

import UIKit

class ViewController: UIViewController ,UICollectionViewDataSource, UICollectionViewDelegate {

    @IBOutlet weak var collectionView: UICollectionView!
var timer : Timer?
var arrayM : [BOModel] = [] {
didSet {
self.collectionView.reloadData()
}
}
static let CellID = "cell"
override func viewDidLoad() {
super.viewDidLoad() self.collectionView.dataSource = self
self.collectionView.delegate = self // 加载数据
loadData()
self.collectionView.register(UINib.init(nibName: "BOCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: ViewController.CellID) //设置collextionView
setupCollectionView() // 开启定时器
starTimer() } /// 从polist中加载数据
func loadData() {
let stemp: NSArray = NSArray(contentsOfFile: Bundle.main.path(forResource: "shops.plist", ofType: nil)!)! for dict in stemp {
let model = BOModel.init(dict: dict as! [String : Any]) self.arrayM.append(model)
}
}
/// 设置cellection的布局方式
///
/// - Returns: 一个布局类型
func setupCollectionFlowlayout() -> (UICollectionViewFlowLayout) {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = self.collectionView.bounds.size
flowLayout.minimumLineSpacing =
flowLayout.minimumInteritemSpacing =
flowLayout.scrollDirection = .horizontal
flowLayout.sectionInset = UIEdgeInsetsMake(, , , )
return flowLayout
} /// 设置collectionVIew
func setupCollectionView() -> () { self.collectionView.collectionViewLayout = self.setupCollectionFlowlayout()
self.collectionView.showsVerticalScrollIndicator = false
self.collectionView.showsHorizontalScrollIndicator = false
self.collectionView.isPagingEnabled = true } // MARK: - 设置数据源
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// print(self.arrayM.count)
return self.arrayM.count *
} func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: ViewController.CellID, for: indexPath) as! BOCollectionViewCell cell.model = self.arrayM[indexPath.row % self.arrayM.count]
return cell
} // MARK: - 实现代理方法
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
//contentOffset.x == 0 时,重新设置contentOffset.x的值
if collectionView.contentOffset.x == {
self.collectionView.contentOffset.x = CGFloat( * self.arrayM.count - ) * self.collectionView.bounds.width }
//当到达最后一个cell时,重新设置contentOffset.x的值
if collectionView.contentOffset.x == CGFloat( * self.arrayM.count - ) * self.collectionView.bounds.width {
self.collectionView.contentOffset.x = CGFloat(self.arrayM.count - ) * self.collectionView.bounds.width
} } /// 开启定时器
func starTimer () {
let timer = Timer.init(timeInterval: , target: self, selector: #selector(ViewController.nextPage), userInfo: nil, repeats: true)
// 这一句代码涉及到runloop 和 主线程的知识,则在界面上不能执行其他的UI操作
RunLoop.main.add(timer, forMode: RunLoopMode.commonModes) self.timer = timer } /// 在1秒后,自动跳转到下一页
func nextPage() {
// 如果到达最后一个,则变成第四个
if collectionView.contentOffset.x == CGFloat( * self.arrayM.count - ) * self.collectionView.bounds.width {
self.collectionView.contentOffset.x = CGFloat(self.arrayM.count - ) * self.collectionView.bounds.width
}else {
// 每过一秒,contentOffset.x增加一个cell的宽度
self.collectionView.contentOffset.x += self.collectionView.bounds.size.width
} } /// 当collectionView开始拖动的时候,取消定时器
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.timer?.invalidate()
self.timer = nil
} /// 当用户停止拖动的时候,开启定时器
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
starTimer()
}
}

plist文件如下图所示:

用到的字典转模型因为比较简单的转换,就自己写了个:

import UIKit

class BOCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var imageView: UIImageView!
var model : BOModel? {
didSet {
guard let image = UIImage.init(named: (model?.name)!) else {
return
} self.imageView.image = image
}
}
override func awakeFromNib() {
super.awakeFromNib() } }

自定义collectionViewCell类中的内容:

import UIKit

class BOCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var imageView: UIImageView!
var model : BOModel? {
didSet {
guard let image = UIImage.init(named: (model?.name)!) else {
return
} self.imageView.image = image
}
}
override func awakeFromNib() {
super.awakeFromNib() } }

附: 其实这种方法比较实现无限滚动,利用了一点小技巧,用电脑测试的时候可能有一点缺陷.

iOScollectionView广告无限滚动(Swift实现)的更多相关文章

  1. iOS开发:一个无限滚动自动播放图片的Demo(Swift语言编码)

    很久以前就想写这么一个无限滚动的Demo了,最近学习了下Swift,手中没有可以用来练手的Demo,所以才将它实现了. Github地址(由于使用了UIView+AutoLayout第三方进行布局,所 ...

  2. iOS swift版本无限滚动轮播图

    之前写过oc版本的无限滚动轮播图,现在来一个swift版本全部使用snapKit布局,数字还是pageConrrol样式可选 enum typeStyle: Int { case pageContro ...

  3. UIScrollView实现图片轮播器的无限滚动

    简介 在现在的一些App中常常见到图片轮播器,一般用于展示广告.新闻等数据,在iOS内并没有现成的控件直接实现这种功能,但是通过UIScrollView的允许分页设置,可以实现滚动轮播的功能. 轮播原 ...

  4. Infinite Scroll - jQuery & WP 无限滚动插件

    无限滚动(Infinite Scroll)也称为自动分页.滚动分页和无限分页.常用在图片.文章或其它列表形式的网页中,用来在滚动网页的时候自动加载下一页的内容.Infinite Scroll  这款  ...

  5. [Unity3D插件]2dtoolkit系列二 动画精灵的创建以及背景图的无限滚动

    经过昨天2dtoolkit系列教程一的推出,感觉对新手还有有一定的启发作用,引导学习使用unity 2dToolKit插件的使用过程,今天继续系列二——动画精灵的创建,以及背景图的无限循环滚动,在群里 ...

  6. 基于HTML5+CSS3的图片旋转、无限滚动、文字跳动特效

    本文分享几种基于HTML5+CSS3实现的一些动画特效:图片旋转.无限滚动.文字跳动;实现起来均比较容易,动手来试试! 一.图片旋转 效果图如下: 这个效果实现起来其实并不困难.代码清单如下: < ...

  7. LoopBar – Tap酒吧与无限滚动

    相约 LoopBar – 标签栏与无限滚动为Android由Cleveroad 在Cleveroad我们最近认识到通过使用任何一个应用程序类别的导航,导航面板是很无聊和琐碎.这就是为什么我们的设计师的 ...

  8. Android 高级UI设计笔记09:Android如何实现无限滚动列表

    ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们提供了一个良好,整洁的用户体验 ...

  9. 无限滚动 --demo

    <!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content=&q ...

随机推荐

  1. 使用 .NET WinForm 开发所见即所得的 IDE 开发环境,实现不写代码直接生成应用程序

    直接切入正题,这是我09年到11年左右业余时间编写的项目,最初的想法很简单,做一个能拖拖拽拽就直接生成应用程序的工具,不用写代码,把能想到的业务操作全部封装起来,通过配置的方式把这些业务操作组织起来运 ...

  2. 调用AJAX做登陆和注册

    先建立一个页面来检测一下我们建立的用户名能不能用,看一下有没有已经存在的用户名吗 可以通过ajax提示一下 $("#uid").blur(function(){ //取用户名 va ...

  3. SQL Server常见数据类型介绍

    数据表是由多个列组成,创建表时必须明确每个列的数据类型,以下列举SQL Server常见数据类型的使用规则,方便查阅. 1.整数类型 int 存储范围是-2,147,483,648到2,147,483 ...

  4. windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...

  5. js:给定两个数组,如何判断他们的相对应下标的元素类型是一样的

    题目: 给Array对象原型上添加一个sameStructureAs方法,该方法接收一个任意类型的参数,要求返回当前数组与传入参数数组(假定是)相对应下标的元素类型是否一致. 假设已经写好了Array ...

  6. HIVE教程

    完整PDF下载:<HIVE简明教程> 前言 Hive是对于数据仓库进行管理和分析的工具.但是不要被“数据仓库”这个词所吓倒,数据仓库是很复杂的东西,但是如果你会SQL,就会发现Hive是那 ...

  7. Nginx反向代理,负载均衡,redis session共享,keepalived高可用

    相关知识自行搜索,直接上干货... 使用的资源: nginx主服务器一台,nginx备服务器一台,使用keepalived进行宕机切换. tomcat服务器两台,由nginx进行反向代理和负载均衡,此 ...

  8. hbase协处理器编码实例

    Observer协处理器通常在一个特定的事件(诸如Get或Put)之前或之后发生,相当于RDBMS中的触发器.Endpoint协处理器则类似于RDBMS中的存储过程,因为它可以让你在RegionSer ...

  9. php安装threads多线程扩展

    php5.3或以上,且为线程安全版本.apache和php使用的编译器必须一致.通过phpinfo()查看Thread Safety为enabled则为线程安全版.通过phpinfo()查看Compi ...

  10. 机器指令翻译成 JavaScript —— No.3 流程分割

    上一篇 我们讨论了跳转指令,并实现「正跳转」的翻译,但最终困在「负跳转」上.而且,由于线程模型的差异,我们不能 1:1 的翻译,必须对流程进行一些改造. 当初之所以选择翻译,而不是模拟,就是出于性能考 ...