今天公司里的实习生跑过来问我一般app上广告的无限滚动是怎么实现的,刚好很久没写博客了,就决定写下了,尽量帮助那些处于刚学ios的程序猿.
做一个小demo,大概实现效果如下图所示:
基本实现思路:
1. 在你需要放置无限滚动展示数据的地方把他的数据,在原本的基础上把你要展示的数据扩大三倍.(当然扩大两倍也是可以的,三倍的话,比较好演示)
?| 1 2 3 4 5 |
// mark: - 设置数据源
func collectionview(_ collectionview: uicollectionview, numberofitemsinsection section: int) -> int {
// print(self.arraym.count)
return self.arraym.count * 3
}
|
2.当在定时器的作用下,或者在拖动情况存下滚动到第八个时候,设置此时的collectionview.contentoffset.x等于滚动到第三个cell的contentoffset.x
| 1 2 3 |
if collectionview.contentoffset.x == cgfloat(3 * self.arraym.count - 1) * self.collectionview.bounds.width {
self.collectionview.contentoffset.x = cgfloat(self.arraym.count - 1) * self.collectionview.bounds.width
}
|
3.当拖动到第0个cell时,设置此时的collectionview.contentoffset.x等于第六个cell的contentoffset.x
| 1 2 3 4 |
if collectionview.contentoffset.x == 0 {
self.collectionview.contentoffset.x = cgfloat(2 * self.arraym.count - 1) * self.collectionview.bounds.width
}
|
代码如下:
我在代码中用到5张照片,所以应该一共有15个cell
?| 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 |
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 = 0
flowlayout.minimuminteritemspacing = 0
flowlayout.scrolldirection = .horizontal
flowlayout.sectioninset = uiedgeinsetsmake(0, 0, 0, 0)
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 * 3
}
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 == 0 {
self.collectionview.contentoffset.x = cgfloat(2 * self.arraym.count - 1) * self.collectionview.bounds.width
}
//当到达最后一个cell时,重新设置contentoffset.x的值
if collectionview.contentoffset.x == cgfloat(3 * self.arraym.count - 1) * self.collectionview.bounds.width {
self.collectionview.contentoffset.x = cgfloat(self.arraym.count - 1) * self.collectionview.bounds.width
}
}
/// 开启定时器
func startimer () {
let timer = timer.init(timeinterval: 1, 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(3 * self.arraym.count - 1) * self.collectionview.bounds.width {
self.collectionview.contentoffset.x = cgfloat(self.arraym.count - 1) * 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文件如下图所示:
用到的字典转模型因为比较简单的转换,就自己写了个:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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类中的内容:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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()
}
}
|
附: 其实这种方法比较实现无限滚动,利用了一点小技巧,用电脑测试的时候可能有一点缺陷.
原文链接:http://www.cnblogs.com/muzichenyu/p/6071757.html
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。








发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。