TL;DR

  • 使用的技术: Compositional layout + Diffable data source。iOS 14+。
  • 创建 layout 以描述布局;
  • 创建 dataSource 以提供数据和 view:
    • 使用 CellRegistration 和 dequeueConfiguredReusableCell 来获取 cell;
    • 使用 SupplementaryRegistration 和 dequeueConfiguredReusableSupplementary 来获取 header、footer 等 supplementary views。

Compositional Layout

如上图所示,一个 compositional layout 由若干个 section 组成,每个 section 又由若干个 group 组成,每个 group 又包含若干个 item,因此,创建一个 layout 的过程即先创建最小展示单元 item 开始,再创建 group,创建 section,创建 layout:

func createBasicListLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(44)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
subitems: [item]
) let section = NSCollectionLayoutSection(group: group) let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}

SectionProvider

如果需要多个布局不同的 sections,可以用下面的构造函数来创建 layout:

// UICollectionViewCompositionalLayout
init(
sectionProvider: @escaping UICollectionViewCompositionalLayoutSectionProvider,
configuration: UICollectionViewCompositionalLayoutConfiguration
)

其中闭包 sectionProvider 用于创建并返回 layout 的各个 secitons,声明如下:

typealias UICollectionViewCompositionalLayoutSectionProvider = (Int, NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection?
// arguments meaning: { sectionIndex, layoutEnvironment in ... }

该闭包也会在一些系统事件触发时被调用,如横竖屏切换、系统字体变更、iPad multitasking 引发的 size class 变更等,可以访问 layoutEnvironment 来获取相关信息,以适配这些场景。

LayoutConfiguration

UICollectionViewCompositionalLayoutConfiguration

  • scrollDirection: UICollectionView.ScrollDirection

    • 滚动方向:.vertical | .horizontal
  • interSectionSpacing: CGFloat
    • Sections 之间的间距
  • contentInsetsReference: UIContentInsetsReference
    • 定义 content inset 时的参考边界
    • .automatic | .none | .safeArea | .layoutMargins | .readableContent
      • 红色为 safeArea,绿色为 layoutMargins,蓝色为 readableContent
  • boundarySupplementaryItems: [NSCollectionLayoutBoundarySupplementaryItem]
    • 在整个 layout 边界处的一些附加 items,如全局 header、全局 footer、badge 等

LayoutEnvironment

包含 layout container 和 environment traits 的信息

  • container: NSCollectionLayoutContainer

    • contentSize: CGSize
    • effectiveContentSize: CGSize:content insets 生效之后的 size
    • contentInsets: NSDirectionalEdgeInsets
    • effectiveContentInsets: NSDirectionalEdgeInsets
  • traitCollection: UITraitCollection

List layout

Compositional layout 专门提供了一个接口来创建 list layout:

static func list(using: UICollectionLayoutListConfiguration) -> UICollectionViewCompositionalLayout

UICollectionLayoutListConfiguration 用于配置 list layout 的一些属性,构造函数中需要指定一个 appearance,如 .plain.sidebar.grouped 等。参见 Apple 文档 来查看可配置的属性,下面列出几种。

  • headerMode

    • .none:不展示 header;
    • .supplementary:使用 supplementary views 来展示 headers;
    • .firstItemInSection:使用 section 中的第一个 item 来作为 header。

Cell view 和 supplementary view 的获取

创建 dataSource 的时候,需要传入一个 cellProvider 来提供 cell view:

dataSource = UICollectionViewDiffableDataSource<Int, UUID>(collectionView: collectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, itemIdentifier: UUID) -> UICollectionViewCell? in
// Configure and return cell.
}

之前我们需要调用 register 方法来注册所需要的 cell 类,然后在 cellProvider 中调用 dequeueReusableCell 方法来获取复用的 cell。iOS 14 提供了一组新的方法,通过 CellRegistration 来配置 cell,然后使用 dequeueConfiguredReusableCell 方法来获取复用的 cell,在调用该方法的时候会自动将 cell 注册到 collectionView 上。如:

let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { cell, indexPath, item in
var contentConfiguration = cell.defaultContentConfiguration() contentConfiguration.text = "\(item)"
contentConfiguration.textProperties.color = .lightGray cell.contentConfiguration = contentConfiguration
} dataSource = UICollectionViewDiffableDataSource<Section, Int>(collectionView: collectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, itemIdentifier: Int) -> UICollectionViewCell? in return collectionView.dequeueConfiguredReusableCell(using: cellRegistration,
for: indexPath,
item: itemIdentifier)
}

注意不要在 cellProvider 里面创建 cell registration,会造成 cell 无法复用,且在 iOS 15+ 上直接报异常

对 cell 的配置通过 UIListContentConfiguration 来完成,调用 cell 的 defaultContentConfiguration 来获取一个包含一些预设属性的 configuration,根据传入的数据对其进行配置,然后再赋值回 cell 的 contentConfiguration。设置 contentConfiguration 会替换掉 cell 现有的 contentView。Cell configuration 具体可参见 Modern cell configuration (WWDC20 10027)

Header、footer 等 supplementary views 的配置和 cell 类似,设置 dataSource 的 supplementaryViewProvider 属性来提供用于创建 view 的闭包,在闭包里面调用 dequeueConfiguredReusableSupplementary 来获取一个复用的 view,该方法接受一个闭包参数 SupplementaryRegistration 来配置 view。

References

iOS Modern Collection View的更多相关文章

  1. Collection View Programming Guide for iOS---(一)----About iOS Collection Views

    Next About iOS Collection Views 关于iOS Collection Views A collection view is a way to present an orde ...

  2. IOS UIView 03- 自定义 Collection View 布局

    注:本人是翻译过来,并且加上本人的一点见解. 前言 UICollectionView 在 iOS6 中第一次被引入,也是 UIKit 视图类中的一颗新星.它和 UITableView 共享一套 API ...

  3. iOS系列译文:自定义Collection View布局

    原文出处: Ole Begemann   译文出处: 黄爱武(@answer-huang).欢迎加入技术翻译小组. UICollectionView在iOS6中第一次被介绍,也是UIKit视图类中的一 ...

  4. Collection View Programming Guide for iOS---(七)---Custom Layouts: A Worked Example

    Custom Layouts: A Worked Example Creating a custom collection view layout is simple with straightfor ...

  5. Collection View Programming Guide for iOS---(五)---Incorporating Gesture Support

      Incorporating Gesture Support 结合手势支持 You can add greater interactivity to your collection views th ...

  6. Collection View Programming Guide for iOS---(三)---Designing Your Data Source and Delegate

      Designing Your Data Source and Delegate 设计你的数据源和委托 Every collection view must have a data source o ...

  7. Collection View 自定义布局(custom flow layout)

    Collection view自定义布局 一般我们自定义布局都会新建一个类,继承自UICollectionViewFlowLayout,然后重写几个方法: prepareLayout():当准备开始布 ...

  8. iOS—使用picker View

    iOS—使用picker View 一.实现效果 说明:点击随机按钮,能够自动选取,下方数据自动刷新. 二.实现思路 1.picker view的有默认高度为162,不可修改. 2.显示数据,需要设置 ...

  9. 自定义 Collection View 布局

    自定义 Collection View 布局 answer-huang 29 Mar 2014 分享文章 UICollectionView 在 iOS6 中第一次被引入,也是 UIKit 视图类中的一 ...

  10. Collection View Programming Guide for iOS---(六)---Creating Custom Layouts

    Creating Custom Layouts 创建自定义布局 Before you start building custom layouts, consider whether doing so ...

随机推荐

  1. 使用python 打包成exe文件

    python 打包exe ​ 起因:闲的蛋疼 ​ 过程:扯的蛋疼 ​ 结果:不疼了 ​ 1.起因(闲的蛋疼) ​ 突然的emo,不想干活,于是乎找遍微信好友,群发了十年八辈子不联系的一群人(此办法学习 ...

  2. .NET周刊【2月第1期 2024-02-04】

    祝大家新年快乐,龙年大吉~ 国内文章 C#/.NET/.NET Core优秀项目和框架2024年1月简报 https://www.cnblogs.com/Can-daydayup/p/18000401 ...

  3. NC19975 [HAOI2008]移动玩具

    题目链接 题目 题目描述 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移 ...

  4. 玩转C语言:深入理解输入输出函数的奥秘

    ​ 欢迎大家来到贝蒂大讲堂 养成好习惯,先赞后看哦~ 所属专栏:C语言学习 贝蒂的主页:Betty's blog 1. 单字符输出函数 在C语言中有一个函数putchar专门负责输出单个字符,其语法如 ...

  5. eclipse安装UML插件

    安装AmaterasUML AmaterasUML 是一个用于 Eclipse 的轻量级 UML 和 ER 图编辑器. 将AmaterasUML的3个jar包拷到Eclpise的plugins文件下: ...

  6. sentry-cli 的 windows 安装

    项目搭建时,发现在使用高版本 sentry-cli 上传 pdb 文件后会报 404 错误,同事猜测高版本的 sentry-cli 会返回错误的地址,建议我用低版本的试一下 依据教程,我在 windo ...

  7. golang中协程&管道&锁

    进程和线程 进程(Process)就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基 本单位,进程是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进 程都有一个自己的地 ...

  8. Ubuntu常用工具和问题整理

    安装Ubuntu虚拟机时常会遇到的几个问题 1.安装时设置镜像 安装Ubuntu系统时设置国内镜像可以加快安装速度:http://mirrors.aliyun.com/ubuntu/ 参考:ubunt ...

  9. Maven应用常见问题

    在Spring Boot项目中打包指定类为启动类 <build> <plugins> <plugin> <groupId>org.springframe ...

  10. Vulnhub靶机网卡启动失败(Raise network interfaces)

    问题 使用一些Linux靶机进行搭建后可能会出现无法搜索到IP的情况,并且会在系统启动时报错,类似下图所示 这个主要是因为vulnhub上的镜像由于搭建环境.版本等问题不适配,网卡没有正确识别导致的, ...