很多时候我们需要列表和宫格视图的来回切换,就像苹果的天气应用一样,我之前见过一个用tableview和collectionview来实现这种效果的,我本人不太喜欢这个,那么有没有更好的方法呢?答案是:有

初识UICollectionView

UICollectionView是一个比UITableView更灵活强大的控件。其他怎么使用这个控件这里不讲述,这里只说列表和宫格的切换。我们查看UICollectionView的API,可以发现有这么一个方法:

open func setCollectionViewLayout(_ layout: UICollectionViewLayout, animated: Bool) // transition from one layout to another

他的解释是转换一个布局到另一个布局。这不就是我们想要的嘛,我们实现两个布局,通过该方法,来回切换布局就行了。

接下来我们通过代码来实现

我们创建一个工程,命名为ListAndGrid,我们直接在默认创建的ViewController中先写这么几个属性

var collectionView: UICollectionView!
var datas: [String] {
var d = [String]()
for i in ... {
d.append("\(i)")
}
return d
}

let listLayout = UICollectionViewFlowLayout() // 列表布局

let gridLayout = UICollectionViewFlowLayout() // 宫格布局

接下来我们在viewDidLoad方法中对这几个属性进行初始设置

代码如下

override func viewDidLoad() {
super.viewDidLoad() listLayout.itemSize = CGSize(width: UIScreen.main.bounds.size.width, height: ) gridLayout.itemSize = CGSize(width: (UIScreen.main.bounds.size.width - ) / 3.0, height: )
gridLayout.minimumLineSpacing =
gridLayout.minimumInteritemSpacing = collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: listLayout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UINib.init(nibName: "LabelCell", bundle: nil), forCellWithReuseIdentifier: "LabelCell") collectionView.backgroundColor = UIColor.white
view.addSubview(collectionView)
// Do any additional setup after loading the view, typically from a nib. }

然后实现UICollectionView相应的代理方法

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return datas.count
} func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LabelCell", for: indexPath) as! LabelCell
cell.label.text = datas[indexPath.row]
return cell
}

至此我们已经实现所有基本代码,接下来我们需要触发setCollectionViewLayout这个方法,我这里是在导航控制器上添加了一个item,这里给出触发事件的代码

@IBAction func clickItem(_ sender: UIBarButtonItem) {
if collectionView.collectionViewLayout == listLayout {
collectionView.setCollectionViewLayout(gridLayout, animated: true)
} else {
collectionView.setCollectionViewLayout(listLayout, animated: true)
}
}

运行程序,效果如下图

切换之后改变cell样式

这是cell样式一样的情况,如果我们要在不用的布局中用不同的cell样式该怎么办呢?

我们首先要在viewDidLoad中添加另一个cell的注册代码,以便复用

collectionView.register(UINib.init(nibName: "LabelCell2", bundle: nil), forCellWithReuseIdentifier: "LabelCell2")

然后func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell代理中也需要做一些改变,我们需要区分是哪种布局,改为下面这样

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView.collectionViewLayout == listLayout {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LabelCell", for: indexPath) as! LabelCell
cell.label.text = datas[indexPath.row]
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LabelCell2", for: indexPath) as! LabelCell2
cell.label.text = datas[indexPath.row]
return cell
}
}

最后关键的地方来了,我们如果用之前的切换布局方法会发现根本达不到目的,我们查看API发现有一个类似的方法是:func setCollectionViewLayout(_ layout: UICollectionViewLayout, animated: Bool, completion: ((Bool) -> Swift.Void)? = nil),这个方法比之前那个多一个完成之后的回调,我们可以利用回调来重新加载一下数据就可以了,这次触发时间里的代码如下:

@IBAction func clickItem(_ sender: UIBarButtonItem) {
if collectionView.collectionViewLayout == listLayout {
collectionView.setCollectionViewLayout(gridLayout, animated: true, completion: { (com) in
if com {
self.collectionView.reloadData()
}
}) } else {
collectionView.setCollectionViewLayout(listLayout, animated: true, completion: { (com) in
if com {
self.collectionView.reloadData()
}
}) }
}

我们是在布局切换完之后又重新刷了一下数据。

运行程序,效果如下

至此,基本的内容已经讲解完,通过这些我们可以完成更复杂的内容

本工程代码请点击下载

利用UICollectionView实现列表和宫格视图的切换的更多相关文章

  1. SharePoint开发 - Excel数据导入到SharePoint自定义列表(数据视图方式)

    博客地址 http://blog.csdn.net/foxdave 本篇讲解一个有些新颖的SharePoint实例应用,给甲方做过项目的都有过体会,数据太多了,客户有Excel,要求实现批量导入. 效 ...

  2. python利用or在列表解析中调用多个函数.py

    python利用or在列表解析中调用多个函数.py """ python利用or在列表解析中调用多个函数.py 2016年3月15日 05:08:42 codegay & ...

  3. [改善Java代码]子列表只是原列表的一个视图

    List接口提供了subList方法,其作用是返回一个列表的子列表.这与String类的subString有点类似.但是他们的功能是否相同?看代码: import java.util.ArrayLis ...

  4. 利用UICollectionView实现瀑布流

    利用UICollectionView实现瀑布流通过自定义布局来实现. - 自定义类继承UICollectionViewLayout: 必须重写的方法有: //决定每个item的位置: - (nulla ...

  5. Jenkins 利用Dashboard View插件管理任务视图

    利用Dashboard View插件管理任务视图   by:授客 QQ:1033553122 步骤 1.  安装Dashboard View插件 说明: 如果无法在线安装,可以选择本地上传方式安装 附 ...

  6. iOS - UICollectionView 瀑布流 添加表头视图的坑

    UICollectionView 瀑布流 添加表头视图的坑 首先是,需求加了个头视图在顶部,在collectionView中的头视图跟TableView的不一样,TableView的表头只要设置tab ...

  7. python3之利用字典和列表实现城市多级菜单

    利用字典和列表实现城市多级菜单 #coding:utf-8 #利用字典和列表实现城市多级菜单 addrIndex = {":"福建"} addrDict = {" ...

  8. C利用可变参数列表统计一组数的平均值,利用函数形式参数栈原理实现指针运算

    //描述:利用可变参数列表统计一组数的平均值 #include <stdarg.h> #include <stdio.h> float average(int num, ... ...

  9. 【逆向工具】IDA使用5-( string、图形化与视图的切换、图形化显示反汇编地址、自动注释、标签使用)

    分析petya病毒时新学会的技巧. IDA技巧1 : string 提取文件中的字符串内容,如果看到一些文件字符串可以定位到关键的函数中. view -> open subview -> ...

随机推荐

  1. API接口签名验证2

    http://www.jianshu.com/p/d47da77b6419 系统从外部获取数据时,通常采用API接口调用的方式来实现.请求方和�接口提供方之间的通信过程,有这几个问题需要考虑: 1.请 ...

  2. ==和equals详解+例子

    一开始遇见==和equals我也是分不清,后来看了很多博客,收益匪浅, 担心以后给忘了,所以写下这个,以后复习可以用. (有哪里写得不对的,希望可以留言帮忙改进,大家一起共同进步) 一.Java数据类 ...

  3. 【开发技术】eclipse中格式化代码快捷键Ctrl+Shift+F失效的解决办法

    要格式化代码的时候,右键-source-format能够起效,但ctrl+shift+f不好使了. 原来是和“简繁体快捷键”冲突了.输入法中的这个快捷键我们一般不用,小勾勾去掉就成了. eclipse ...

  4. 无法打开物理文件 操作系统错误 5:拒绝访问 SQL Sever

    今天分离附加数据库,分离出去然后再附加,没有问题.但是一把.mdf文件拷到其它文件夹下就出错,错误如下:    无法打开物理文件 "E:\db\homework.mdf".操作系统 ...

  5. Python解析JSON详解

    JSON 函数 使用 JSON 函数需要导入 json 库:import json. 函数  描述 json.dumps  将 Python 对象编码成 JSON 字符串 json.loads  将已 ...

  6. jQuery hover() 方法

    $("p").hover(function(){ $("p").css("background-color","yellow&qu ...

  7. .net Core连接MongoDB

    前两天在学习MongoDB相关的知识,做了个小Demo,大概是省份里面有多少所学校 连接MongoDB首先要通过Nuget添加一个MongoDB的包,下载此包 安装完毕后开始写代码了,创建一个省份实体 ...

  8. .net Core学习笔记1 创建简单的 .net core项目

    1.打开vs2017>Web 1:创建实体类: namespace ProductMvc.Models { //商品类型 public class ProductType { public in ...

  9. x64内核HOOK技术之拦截进程.拦截线程.拦截模块

    x64内核HOOK技术之拦截进程.拦截线程.拦截模块 一丶为什么讲解HOOK技术. 在32系统下, 例如我们要HOOK SSDT表,那么直接讲CR0的内存保护属性去掉. 直接讲表的地址修改即可. 但是 ...

  10. Log4j扩展使用--自定义输出

    写在前面的话 log4j支持自定义的输出.所有的输出都实现了自Appender接口.一般来说,自定义输出值需要继承AppenderSkeleton类,并实现几个方法就可以了. 写这篇博客,我主要也是想 ...