61 - Swift 之 UICollectionView 的使用和介绍

一、UICollectionView 的介绍

  • UICollectionViewLayout类是一个抽象类的子类化来定义自定义布局集合。定义一个自定义的布局是一种先进的复杂操作的应用程序的需求。

  • UICollectionViewFlowLayout 是 UICollectionViewLayout 的子类,是一个方便于处理页面布局的类。即是可以直接使用不需要其他操作。

二、 UICollectionViewFlowLayout 的创建和参数的介绍

// TODO: 一般UICollectionViewFlowLayout 的创建
func ctreateFlowLayout() -> UICollectionViewFlowLayout {
    let FlowLayout = UICollectionViewFlowLayout.init()
    // 最小间隔
    FlowLayout.minimumLineSpacing = 1
    // 临时的最小间隔
    FlowLayout.minimumInteritemSpacing = 0.5
    // 设置大小
    FlowLayout.itemSize = CGSize.init(width: self.view.frame.width, height: 200)
    // 设置 Item 的滚动方向
    FlowLayout.scrollDirection = .horizontal
    // 设置 UICollectionView 的headerView 和 footerView 的大小
    FlowLayout.headerReferenceSize = CGSize.zero
    FlowLayout.footerReferenceSize = CGSize.zero
    // 设置 UICollectionView 的Section 的偏移
    FlowLayout.sectionInset = UIEdgeInsets.zero
    // 设置 UICollectionView 的 headerView 和 footerView 能够悬浮在屏幕的顶部
    FlowLayout.sectionFootersPinToVisibleBounds = true
    FlowLayout.sectionHeadersPinToVisibleBounds = true
    return FlowLayout
}

三、 UICollectionView 的简单创建 和 参数的介绍使用

1> 简单的创建 UICollectionView的对象

// 创建一个 CollectionView 的对象
let collectionView = UICollectionView.init(frame: self.view.frame, collectionViewLayout: self.ctreateFlowLayout())
// 设置 CollectionView 的两个代理,分别是 UICollectionViewDelegate 和 UICollectionViewDataSource
collectionView.delegate = self
collectionView.dataSource = self
// 预加载的代理
collectionView.prefetchDataSource = self
// 进行渲染
self.view.addSubview(collectionView)
// 注册 UICollectionView 的 cell / headerView /footerView
collectionView .register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell_id")
collectionView.register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header_id")
collectionView.register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "footer_id")

2> 参数的介绍

// 设置背景View
collectionView.backgroundView = UIView.init()
// Collection 是否允许预加载
collectionView.isPrefetchingEnabled = true
// 设置 UICollectionView 的 item 是否能够被选中
collectionView.allowsSelection = true
// 设置 UICollectionView 的item 能够多选
collectionView.allowsMultipleSelection = true
// 让 UICollectionView 自动滑动到指定Section的Item 的位置
collectionView.scrollToItem(at: IndexPath.init(row: 2, section: 2), at: .top, animated: true)
// 让 UICollectionView 自动选择指定的Item。并将选中的Item滑动到指定的位置
collectionView.selectItem(at: IndexPath.init(row: 1, section: 3), animated: true, scrollPosition: .top)
// 取消选中的item
collectionView.deselectItem(at: IndexPath.init(row: 1, section: 3), animated: true)
// UICollectionView 的整体更新数据的方法
collectionView.reloadData()
// 设置 UICollectionView 的新的布局,从一个布局到另一个布局的转变
collectionView.setCollectionViewLayout(self.ctreateFlowLayout(), animated: true)
collectionView.setCollectionViewLayout(self.ctreateFlowLayout(), animated: true) { (isFinsish) in
     // 这里可以等布局完成后在做一些其他的操作
}

// 准备好动画,调用该方法开始动画对collectionView进行布局,成功后就会回调 setCollectionViewLayout:animated :{} 方法
collectionView.finishInteractiveTransition()
// 取消对collectionView布局的动画,并回调 setCollectionViewLayout:animated :{} 该方法
collectionView.cancelInteractiveTransition()

// 获取 collectionView 的整个 Section 的个数
let totalSection = collectionView.numberOfSections
print(totalSection)
// 获取 collectionView 的某一个 Section 中 item 的个数
let itemCount = collectionView.numberOfItems(inSection: 2)
print(itemCount)

// 获取 collectionView 的 Item 属性
let ItemLayoutAttributes =  collectionView.layoutAttributesForItem(at: IndexPath.init(row: 1, section: 2))
// UICollectionViewLayoutAttributes 属性我们可以获取一些关于itme的属性,例如:大小、透明度、是否隐藏、IndexPath ... 等
print((ItemLayoutAttributes?.frame,ItemLayoutAttributes?.size,ItemLayoutAttributes?.indexPath,ItemLayoutAttributes?.alpha))

// 获取 collectionView 的 ReusableView 的一些属性
let ReusableViewLayoutAttributes = collectionView.layoutAttributesForSupplementaryElement(ofKind: UICollectionElementKindSectionHeader, at: IndexPath.init(item: 0, section: 2))
// UICollectionViewLayoutAttributes 属性我们可以获取一些关于ReusableView的属性,例如:大小、透明度、是否隐藏、IndexPath ... 等
print((ReusableViewLayoutAttributes?.frame,ReusableViewLayoutAttributes?.size,ReusableViewLayoutAttributes?.indexPath,ReusableViewLayoutAttributes?.alpha))

// 通过collectionView 的Item上某一点获取改 Item 的 indexPath

let point_indexPath = collectionView.indexPathForItem(at: CGPoint.init(x: 100, y: 200))
// 通过 point_indexPath 就可以知道你点击的是哪个 Section 的 item
print((point_indexPath?.row ,point_indexPath?.section))

// 通过 UICollectionViewCell 来获取 indexPath
let cell_indexPath = collectionView.indexPath(for: UICollectionViewCell.init())
// 通过 cell_indexPath 就可以知道你点击的是哪个 Section 的 item
print((cell_indexPath?.row ,cell_indexPath?.section))

// 通过indexPath 来获取 cell
let Index_cell = collectionView.cellForItem(at: IndexPath.init(row: 2, section: 2))
print(Index_cell!)

// 获取 UICollectionView 视图可见的 Cell
let AbleCells = collectionView.visibleCells
print(AbleCells)

// 获取视图上可见的 Item 的 indexPath
let Item_indexPaths = collectionView.indexPathsForVisibleItems
print(Item_indexPaths)

// 通过指定的indexPath 还获取 UICollectionView的 headerView & fotterView
let XReusableView = collectionView.supplementaryView(forElementKind: UICollectionElementKindSectionHeader, at: IndexPath.init(row: 0, section: 2))
print(XReusableView!)

// 通过给定的类型(UICollectionElementKindSectionHeader、UICollectionElementKindSectionFooter)来获取视图可见的 headerView & footerView 
let XReusableViews = collectionView.visibleSupplementaryViews(ofKind: UICollectionElementKindSectionHeader)
print(XReusableViews)

// 通过给定的类型 (UICollectionElementKindSectionHeader、UICollectionElementKindSectionFooter)来获取视图可见的 indexPath 
let indexPaths = collectionView.indexPathsForVisibleSupplementaryElements(ofKind: UICollectionElementKindSectionHeader)
print(indexPaths)

// MARK: UICollectionView 的Section 的增加、删除、刷新、移动
let set = NSIndexSet.init(indexesIn: NSRange.init(location: 0, length: 3))
//  UICollectionView 的Section 的插入操作
collectionView.insertSections(set as IndexSet)
//  UICollectionView 的Section 的删除操作
collectionView.deleteSections(set as IndexSet)
//  UICollectionView 的Section 的数据刷新操作
collectionView.reloadSections(set as IndexSet)
//  UICollectionView 的Section 移动到另一个新的位置
collectionView.moveSection(0, toSection: 3)

// MARK: UICollectionView 的 Item 的增加、删除、刷新、移动
// UICollectionView 的 Item 的插入操作
collectionView.insertItems(at: [IndexPath.init(row: 1, section: 1)])
// UICollectionView 的 Item 的删除操作
collectionView.deselectItem(at: IndexPath.init(row: 0, section: 1), animated: true)
// UICollectionView 的 Item 的刷新操作
collectionView.reloadItems(at: [IndexPath.init(row: 0, section: 1)])
// UICollectionView 的 Item 的移动操作
collectionView.moveItem(at: IndexPath.init(row: 0, section: 1), to: IndexPath.init(row: 0, section: 2))
// UICollectionView 的Section 或者 Item 的增加、删除、刷新、移动调用的函数
collectionView.performBatchUpdates({ 
    // 要更新的 Layout
}) { (isFinsh) in
    // 判断是否完成,再做其他事情
}

// 是否在移动的时候,对 UICollectionView 的 Item 进行排序,返回一个BOOl 值,默认情况是 true
collectionView.beginInteractiveMovementForItem(at: IndexPath.init(row: 0, section: 2))
// 更新 UICollectionView 的 Item 移动时的点(位置)
collectionView.updateInteractiveMovementTargetPosition(CGPoint.init(x: 100, y: 30))
// 移动Item到新的点
collectionView.endInteractiveMovement()
// 将item恢复到原始的点
collectionView.cancelInteractiveMovement()

四、 UICollectionView 的代理方法的介绍

1> UICollectionViewDelegate 的所有代理介绍

// MARK: UICollectionViewDelegate 的代理方法的实现

// TODO: 设置CollectionView 的 Item 是否点击Item变为高亮状态。返回结果: true 点击Item 变为高亮状态;false  点击不变为高亮状态
func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
     return true
}

// TODO: UICollectionView 哪一个Item 被点击成为高亮状态后调用该函数
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
    print("高亮" + "\(indexPath.section)" + "--" + "\(indexPath.row)")
}

// TODO: UICollectionView的Item有高亮状态变为非高亮状态时调用的函数
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
     print("不高亮" + "\(indexPath.section)" + "--" + "\(indexPath.row)")
}

// TODO: 设置 UICollectionView 是否允许取消选中
func collectionView(_ collectionView: UICollectionView, shouldDeselectItemAt indexPath: IndexPath) -> Bool {
    return true
}

// TODO: UICollectionView 的 Item 点击选中触发该方法
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    print("Item 被选中")
}

// TODO: UICollectionView 的取消选中操作时调用的函数
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    
}


// TODO: UICollectionViewCell 将要显示在视图上的时候调用该函数
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    print("将要显示的cell" + "\(indexPath.section)" + "\(indexPath.row)")
}

// TODO: UICollectionViewCell 显示结束,指的是Cell滑动移出视图时调用该函数
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    print("cell 显示结束" + "\(indexPath.section)" + "\(indexPath.row)")
}

// TODO: UICollectionView 的headerView 和 footerView 将要出视图的时调用
func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) {
    print("headerView 和 footerView 将要出现在当前视图")
}

// TODO: UICollectionView 的headerView 和 footerView 滑动移出视图的时调用
func collectionView(_ collectionView: UICollectionView, didEndDisplayingSupplementaryView view: UICollectionReusableView, forElementOfKind elementKind: String, at indexPath: IndexPath) {
    print("headerView 和 footerView 被移出当前视图")
}


// TODO: 是否允许 Item 是否显示菜单(Cut/Copy/Paste)
func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool {
     return true
}

// TODO: 设置是否允许菜单内显示那些按钮
func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
    // 我们可以控制菜单内的按钮显示
    if action == #selector(UIResponderStandardEditActions.cut(_:)){
        return false
    }
    return true
}

// TODO: 用户点击菜单内的按钮触发的函数
func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) {
    print("菜单内的按钮被点击")
}

// TODO: 设置 UICollectionView 的 Item 是否可以选择。返回结果:true 可以选择 、 false 不可以选择
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
     return true
}

// TODO: UICollectionView 重新布局调用该方法
func collectionView(_ collectionView: UICollectionView, transitionLayoutForOldLayout fromLayout: UICollectionViewLayout, newLayout toLayout: UICollectionViewLayout) -> UICollectionViewTransitionLayout {
    let  TransitionLayout = UICollectionViewTransitionLayout.init(currentLayout: self.ctreateFlowLayout(), nextLayout: self.ctreateFlowLayout())
    return TransitionLayout
}

2> UICollectionViewDataSource 代理的介绍

// MARK: UICollectionViewDataSource 的代理事件

// TODO: 设置 UICollectionView 的每一个组(Section),含有Item 的个数
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 6
}

// TODO: 设置UICollectionView返回的组数(Section)
func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 6
}

// TODO: 这是设置 UICollectionView 的cell 的布局函数
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // 创建 CollectionView 的cell
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell_id", for: indexPath)
    // 设置简单的样式
    cell.contentView.backgroundColor = UIColor.red
    // 返回变量
    return cell
}

// TODO: 设置 UICollectionView 的 headerView & footerView
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    // 创建一个中间变量
    var IdentifierStr =  String.init()
    // 判断是headerView & footerView
    if kind == UICollectionElementKindSectionHeader {
        IdentifierStr = "header_id"
    }else if (kind == UICollectionElementKindSectionFooter) {
        IdentifierStr = "footer_id"
    }
    // 创建一个 UICollectionReusableView 对象
    let reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: IdentifierStr, for: indexPath)
    if kind == UICollectionElementKindSectionHeader {
        reusableView.backgroundColor = UIColor.magenta
    }else if (kind == UICollectionElementKindSectionFooter){
        reusableView.backgroundColor = UIColor.green
    }
    // 返回 UICollectionReusableView 类的对象
    return reusableView
}

// TODO: CollectionView 的编辑时设置是否可以移动 Item
func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
    return true
}

// TODO: UICollectionView 的 Items 移动后,数据资源也要变更
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    /* 这更新原始数据库为变更后的数据结构 */
}

// TODO: UICollectionView 的索引返回参数
func indexTitles(for collectionView: UICollectionView) -> [String]? {
    return ["A","B","C","D","E","s"]
}


func collectionView(_ collectionView: UICollectionView, indexPathForIndexTitle title: String, at index: Int) -> IndexPath {
    print(title)
    print(index)
    return IndexPath.init()
}

3> UICollectionViewDelegateFlowLayout 的代理介绍

// MARK: UICollectionViewDelegateFlowLayout 的代理事件

// TODO:设置 UICollectionView 的 Item 的大小(宽、高)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
     return CGSize.init(width: collectionView.frame.width, height: 60)
}

// TODO: 设置 UICollectionView 的 Section 的上、下、左、右 的偏移
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets.init(top: 20, left: 0, bottom: 40, right: 0)
}

// TODO: 设置 UICollectionView 的 Section 的 HeaderView 的大小(宽、高)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
     return CGSize.init(width: self.view.frame.width, height: 30)
}

// TODO: 设置 UICollectionView 的 Section 的 footerView 的大小(宽、高)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
     return CGSize.init(width: self.view.frame.width, height: 30)
}

// TODO: 设置 UICollectionView 的 items 之间的上下临时最小间距
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 3
}

// TODO: 设置 UICollectionView 的 items 之间的上下最小间距
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
     return  5
}

4> UICollectionViewDataSourcePrefetching 的代理方法的介绍

// MARK: UICollectionView 预先加载的数据
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
    //获取cell ,赋值数据
}
// MARK: UICollectionView 取消预先加载的数据
func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {
    // 取消预加载
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容