很多时候我们需要列表和宫格视图的来回切换,就像苹果的天气应用一样,我之前见过一个用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. removeClass()

    定义和用法 removeClass() 方法从被选元素移除一个或多个类. 注释:如果没有规定参数,则该方法将从被选元素中删除所有类. 语法 $(selector).removeClass(class) ...

  2. Java 对二值化图片识别连通域

    用Java 对 已经 二值化了的图片 标记连通域 每块的连通域都标记不一样的数字 public static void main(String [] args) throws IOException ...

  3. Struts2中Action接收参数的方法主要有以下三种:

    Struts2中Action接收参数的方法主要有以下三种: 1.使用Action的属性接收参数(最原始的方式):     a.定义:在Action类中定义属性,创建get和set方法:     b.接 ...

  4. Springmvc 并发访问的线程安全性问题

    首先对于spring的IOC来说,对象是由Spring来帮我们管理,也就是在Spring启动的时候,在Spring容器中,由Spring给我们创建的,Spring会帮我们维护,一般都是单例的,也就是一 ...

  5. LinkedList 源码分析(JDK 1.8)

    1.概述 LinkedList 是 Java 集合框架中一个重要的实现,其底层采用的双向链表结构.和 ArrayList 一样,LinkedList 也支持空值和重复值.由于 LinkedList 基 ...

  6. python下划线作用初识

    单下划线(例:_textchar) 以单下划线做前缀的名称指定了这个名称是"私有的".在 有些 导入import * 的场景中,下一个使用你代码的人(或者你本人)会明白这个名称仅内 ...

  7. 配置SESSION超时与请求超时

    <!--项目的web.xml中 配置SESSION超时,单位是min.用户在线时间.如果不设置,tomcat下的web.xml的session-timeout为默认.--><sess ...

  8. 转-Linux硬件装置和磁盘分区MBR

    1 各硬件装置在Linux中的文件名 『在Linux系统中,每个装置都被当成一个文件来对待』 举例来说,SATA接口的硬盘的文件名即为/dev/sd[a-d],其中, 括号内的字母为a-d当中的任意一 ...

  9. Arrays.sort解析

    Arrays.sort()解读 在学习了排序算法之后, 再来看看 Java 源码中的, Arrays.sort() 方法对于排序的实现. 都是对基本数据类型的排序实现, 下面来看看这段代码: Arra ...

  10. spark-遇到问题小结

     经常会遇到 类似 shuffle 0 的错误,或者 connect refuse .主要是shuffle 导致内存不足引起的.shuffle 分为 shuffle read 和write . 1. ...