UICollectionView-集合视图(理论篇)
来源:互联网 发布:淘宝管控商品怎么上架 编辑:程序博客网 时间:2024/06/15 05:03
UICollectionView-集合视图(理论篇 + 简单demo)
前言:
本文部分理论摘抄自网络(感谢各位大神的分享!),自己稍加整理,然后加上自己的理解再修饰。文章最后以示例代码的形式展示了怎么运用,用于备忘。
1. 概述:
UICollectionView 多列的UITableView(最简单的形式),类似于iBooks中书架的布局。
最简单的UICollectionView是一个GridView,可以多列的方式进行展示。
实现垂直方向的单列表来说,使用UITableView足以;若是需要构建横向滑动列表、gridView等直线型布局,则使用UICollectionView+UICollectionViewFlowLayout搭建最合适;更复杂的布局,则可以使用UICollectionView+自定义Layout来实现。
2. 组成
Cells:
用于展示内容主体:对不同的cell可以定制不同尺寸和不同内容。它是从数据源对象获取的
Supplementary Views:
追加视图: 类似于tableview中,每个Section的Header或者 Footer。它是从数据源方法当中获取的,但是与cell不同的是,它并不是强制需要的。
Decoration Views:
装饰视图:每个section的背景,它没有什么功能性,它不跟数据源有任何关系,它完全属于layout对象。
3. 工作原理
当UICollectionView显示内容时,先从dataSource数据源获取cell,然后交给UICollectionView。再从UICollectionViewLayout获取对应的layout attributes(布局属性)。最后,根据每个cell对应的layout attributes(布局属性)来对cell进行布局,生成了最终的界面。而用户交互的时候,都是通过Delegate来进行交互。当然,上面只是布局cell,但是UICollectionView内部还有Supplementary View和Decoration View,也可以对其进行布局。
4. 使用基本步骤
1) viewController:UICollectionViewDataSource, UICollectionViewDelegate 遵循这两个协议
2) 注册复用的cell(必须) 及 supplementaryView(如果需要)
3) 实现UICollectionViewDataSource及UICollectionViewDelegate协议的方法
5. 复用cell及Supplementary View
5.1 注册
在使用数据源返回cell或者Supplementary View给collectionView之前,我们必须先要注册,用来进行重用。
registerClass:forCellWithReuseIdentifier:
registerNib:forCellWithReuseIdentifier:
registerClass:forSupplementaryViewOfKind:withReuseIdentifier:
registerNib:forSupplementaryViewOfKind:withReuseIdentifier:
显而易见,前面两个方法是注册cell,后两个方法注册Supplementary View。其中,注册的方式有两种,第一种是直接注册class,这样的初始化方法创建cell;另外一种是注册nib,它会自动加载nib文件。
注册示例代码如下:
self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier:”cell”)
5.2 获取
在数据源方法当中返回cell或者Supplementaryview的方法当中通过
dequeueReusableCellWithReuseIdentifier:forIndexPath:
dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:
方法获取cell或者SupplementaryView。
6. dataSource-数据源方法
数据源方法与UITableView类似,主要有:
numberOfSectionsInCollectionView://集合共有多少个部分
collectionView:numberOfItemsInSection://每个部分有多少个元素
collectionView:cellForItemAtIndexPath://复用cell
collectionView: viewForSupplementaryElementOfKind:atIndexPath: //复用supplementrayViews
与UITableView不同的是多加了返回Supplementary view数据源方法。
7. delegate-代理方法
数据源为UICollectionView提供数据相关的内容,而代理则主要负责用户交互、与数据无关的视图外形。主要分成两部分:
7.1 通过调用代理方法,管理视图的选中、高亮
-1.collectionView:shouldHighlightItemAtIndexPath: //是否应该高亮?
-2.collectionView:didHighlightItemAtIndexPath: //如果1回答为是,那么高亮
-3.collectionView:shouldSelectItemAtIndexPath: //无论1结果如何,都询问是否可以被选中?
-4.collectionView:didUnhighlightItemAtIndexPath: //如果1回答为是,那么现在取消高亮
-5.collectionView:didSelectItemAtIndexPath:// 如果3回答为是,那么选中cell
7.2 长按cell,显示编辑菜单
与UITableView不同,用户长按cell时,UICollectionView可以显示编辑菜单。这个编辑菜单可以用来剪切、复制和粘贴cell。不过,要显示这个编辑菜单需要满足下面几个条件:
代理对象必须实现下面三个方法:
collectionView:shouldShowMenuForItemAtIndexPath:
collectionView:canPerformAction:forItemAtIndexPath:withSender:
collectionView:performAction:forItemAtIndexPath:withSender:
对于指定要编辑的cell,collectionView:shouldShowMenuForItemAtIndexPath:方法需要返回YES
collectionView:canPerformAction:forItemAtIndexPath:withSender: 方法中,对于剪切、复制、粘贴三种action至少有一个返回YES。其实,编辑菜单是有很多种action的,但是对于UICollectionView来说,它仅仅支持的剪切、复制、粘贴三个,所以说这个代理方法至少支持这三种的一种。
剪切、复制、粘贴的方法名是: cut: copy: paste:
如下图所示:
当上面的条件都满足了,用户就可以长按cell显示出编辑菜单,然后选择对应的action,从而就会回调delegate的collectionView:performAction:forItemAtIndexPath:withSender: 方法去做对应的事情。
当我们想控制编辑菜单仅仅显示复制和粘贴时,我们就可以用collectionView:canPerformAction:forItemAtIndexPath:withSender: 方法阻止剪切按钮出现在编辑菜单里。
func collectionView(collectionView: UICollectionView, canPerformAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool { print("action:\(NSStringFromSelector(action))") if action == "cut:" { return false } return true }
隐藏cut效果图如下:
8. Demo (纯代码实现)
运行效果图:
说明:图中红色的为header,橙色的为footer,详情见代码定义。//class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { //定义集合视图 var collectionView: UICollectionView! //定义元素标示 let cellIndentifier = "cell" override func viewDidLoad() { super.viewDidLoad() //设置布局方式为flowLayout let layout = UICollectionViewFlowLayout() //设置item之间的距离 layout.minimumInteritemSpacing = 15 //设置section边界 layout.sectionInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) //设置item行距 layout.minimumLineSpacing = 28 //设置supplementaryView header的尺寸, 不设置则不会显示header layout.headerReferenceSize = CGSize(width: view.bounds.size.width, height: 10) //设置supplementaryView footer的尺寸,不设置则不会显示footer layout.footerReferenceSize = CGSize(width: view.bounds.size.width, height: 10) self.collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height), collectionViewLayout: layout) //设置代理 self.collectionView.delegate = self //设置数据源 self.collectionView.dataSource = self //注册复用的元素 self.collectionView.registerClass(UICollectionViewCell.self , forCellWithReuseIdentifier: cellIndentifier) //注册header self.collectionView.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind:UICollectionElementKindSectionHeader , withReuseIdentifier: "headView") //注册footer self.collectionView.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind:UICollectionElementKindSectionFooter , withReuseIdentifier: "footView")// self.collectionView.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind:"customView" , withReuseIdentifier: "customView") self.collectionView.backgroundColor = UIColor.grayColor() self.view.addSubview(collectionView) } //MARK: UICollectionViewDataSource实现方法 //配置每个部分(section)有多少个元素(item) func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 10 } //配置集合视图(collectionView)有多少个部分(section) func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { return 10 } func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { // 取得元素 let cell = self.collectionView.dequeueReusableCellWithReuseIdentifier(cellIndentifier, forIndexPath: indexPath) //配置元素 cell.layer.masksToBounds = true// cell.layer.cornerRadius = 25 //取得随机颜色:颜色值在0到1至之间,除以255.0为了得到小数 cell.backgroundColor = UIColor(red: CGFloat(Double(random() % 255) / 255.0), green: CGFloat(Double(arc4random() % 255) / 255.0), blue: CGFloat(Double(arc4random() % 255) / 255.0), alpha: 1) return cell } //配置supplementaryView func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { var view: UICollectionReusableView! = nil if kind == UICollectionElementKindSectionHeader { view = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "headView", forIndexPath: indexPath) view.backgroundColor = UIColor.redColor() } else if kind == UICollectionElementKindSectionFooter { view = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "footView", forIndexPath: indexPath) view.backgroundColor = UIColor.orangeColor() } return view } // MARK: UICollectionViewDelegate // Uncomment this method to specify if the specified item should be highlighted during tracking func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool { return true } //执行高亮显示 func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath) { let cell = collectionView.cellForItemAtIndexPath(indexPath) cell?.contentView.backgroundColor = UIColor.whiteColor() } //取消高亮显示 func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) { let cell = collectionView.cellForItemAtIndexPath(indexPath) cell?.contentView.backgroundColor = nil } // Uncomment this method to specify if the specified item should be selected func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool { return true } //- ----配置编辑菜单------------------- // Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item func collectionView(collectionView: UICollectionView, shouldShowMenuForItemAtIndexPath indexPath: NSIndexPath) -> Bool { return true } func collectionView(collectionView: UICollectionView, canPerformAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool { print("action:\(NSStringFromSelector(action))") if action == "cut:" { return false } return true } func collectionView(collectionView: UICollectionView, performAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) { print("performAction------") }}
- UICollectionView-集合视图(理论篇)
- UICollectionView 的应用 (集合视图)
- 关于集合视图UICollectionView
- UICollectionView 集合视图
- UICollectionView 集合视图详解
- UICollectionView 集合视图详解
- iOS8 UICollectionView 集合视图
- UICollectionView 集合视图
- 42.集合视图(UICollectionView)
- UICollectionView 集合视图
- 集合视图UICollectionView
- 集合视图 UICollectionView
- 52.集合视图UICollectionView
- UICollectionView-集合视图
- UICollectionView 集合视图 的使用
- OCiOS开发:集合视图 UICollectionView
- iOS开发 -- UICollectionView(集合视图)
- iOS开发:集合视图 UICollectionView
- 给 Android 开发者的 RxJava 详解 Observable
- leetcode之Combination Sum
- Unicode原理
- 内部排序算法总结
- 插入排序
- UICollectionView-集合视图(理论篇)
- 利用缓存存储网络下载的图片
- Android与Java中的ThreadLocal
- eclipse如何快速查找某个类
- Spark代码1之RDDparallelizeSaveAsFile
- 【JAVA知识】IO流(1)
- Java集合框架
- 利用gitbash上传项目到github
- 30-题目1172:哈夫曼树