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

    http://blog.csdn.net/phper8/article/details/76383415 学习内容: https://www.kancloud.cn/tpshop/thinkphp5/ ...

  2. 如何设置让网站禁止被爬虫收录?robots.txt

    robot.txt只是爬虫禁抓协议,user-agent表示禁止哪个爬虫,disallow告诉爬出那个禁止抓取的目录. 如果爬虫够友好的话,会遵守网站的robot.txt内容. 一个内部业务系统,不想 ...

  3. 5.04 toArray()有一个问题须要解决一下

    把查询数据转为数组输出,这个toArray()方法是把对像转为数组输出,本身是没啥 问题.但是里面好像少写了一句判断:应先判断这个对像是否为空!如果为空则不转换直接输出空就行了吗,否则一个空值去转成数 ...

  4. 在ASP.NET Core中通过EF Core实现一个简单的全局过滤查询

    前言 不知道大家是否和我有同样的问题: 一般在数据库的设计阶段,会制定一些默认的规则,其中有一条硬性规定就是一定不要对任何表中的数据执行delete硬删除操作,因为每条数据对我们来说都是有用的,并且是 ...

  5. NumPy-矩阵部分

    NumPy-矩阵部分 [TOC] NumPy 简介 numpy可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多. 安装NumPy pi ...

  6. 找不到javax.servlet.Filter类,

    找不到javax.servlet.Filter类, 在构建的依赖包中缺少servlet.api

  7. linux_samba服务安装

    什么是samba服务? 用于Windows和linux系统之间实现共享文件的目的服务 如何配置其服务? Linux端: 搭建服务 1. 安装samba yum install -y samba 2. ...

  8. Servlet--Servlet接口

    servlet主要数据结构 Servlet 接口:主要定义了servlet的生命周期方法 ServletConfig接口:为servlet提供了使用容器服务的若干重要对象和方法. ServletCon ...

  9. Struts2 (二)

    1 自定义结果视图 1.1 自定义一个类实现com.opensymphony.xwork2.Result接口. package com.xuweiwei.action; import com.open ...

  10. CentOS7修改主机名(hostname)

    Linux中的hostname在大多数应用中至为重要,例如有些应用强制使用主机名称而不能使用IP地址,如果默认主机名称都为localhost.localdomain 的话那一定会出现问题,而且看起来也 ...