使用流式布局
你可以使用具体的布局对象( UICollectionViewFlowLayout
类)在集合视图中排列items
。流式布局实现了基于行的断裂布局,这意味着布局对象将单元格放置在一条线性路径上,并尽可能地沿着该行容纳多个单元格。当布局对象在当前行上的空间不足时,会创建一个新的行,并且继续进行布局过程。图3-1显示垂直滚动流式布局的外观。在这种情况下,线条水平排列,每一条新线位于前一条线之下。每一个分区的单元格可以选择性地用分区头和分区尾视图来围绕。
你可以使用流式布局来实现网格,也可以使用它来做更多其他的工作。线性布局的思想可以应用于很多不同的设计。例如,你可以调整间距沿着一个滚动维度来创建items
的一行,而不是具有items
的网格。items
可以是不同的大小,这产生比传动网格更不对称的东西,但仍然具有线性流动性。这里有多种可能。
在xcode中你可以使用编程代码或界面构建器来配置流式布局。配置的步骤如下:
- 创建一个流式布局对象并把它赋值给集合视图
- 配置
cells
的宽高 - 设置线间距和
items
之间的间距 - 如果想要分区头和分区尾,指定它们的大小
- 给布局设置滚动方向
重要:至少必须指定
cells
的宽高。如果没有,items
的宽高默认为0,将永不可见。
自定义流式布局属性
流式布局公开了几个属性来配置内容的外观。当设置的时候,这些属性将在布局中均等地应用于所有items
。例如,使用流式布局的itemSize
属性来设置cell
的大小会造成所有的cells
有相同的大小。
如果你想要动态改变items
的间距或大小,可以使用UICollectionViewDelegateFlowLayout
协议中的方法。在赋值给集合视图的同一委托对象上实现这些方法。如果存在给定的方法,则流式布局对象会调用该方法,代替使用它具有的固定值。然后,你的视线必须为集合视图中的所有items
返回适当的值。
在流式布局中指定items
的大小
如果集合视图中所有的items
都是相同的大小,那就给流式布局对象的itemSize
属性赋值合适的宽高值。(始终以点为单位指定items
的大小)。这是为大小不变的内容配置布局对象的最快方式。
如果你想要给你的cells
指定不同的大小,你必须实现集合视图代理的collectionView:layout:sizeForItemAtIndexPath:
方法。你可以使用提供的索引路径信息来给相应的item
返回大小。在布局期间,流式布局对象在同一行上垂直居中,如图3-2所示。然后,该线的整体高度和宽度由该维度中的最大item
确定。
注意:当你为
cells
指定不同大小,单行上的items
数可能会有所不同。
指定items
和行之间的间距
使用流式布局,你可以指定同一行上的items
之间的最小间距和连续行之间的最小间距。请记住, 提供的间隔只是最小间隔。因为如何布局内容,流式布局对象可能将item
之间的间距增大到大于指定的值。当被布局的items
是不同大小时,布局对象可以类似地增加实际的行间距。
在布局期间,流式布局对象将items
添加到当前行,直到没有足够的空间来适应整个item
。如果线足够大,以适应没有额外空间的整数个items
,那么这些items
之间的间距将等于最小间距。如果在线的末尾有额外的空间,则布局对象会增加间隔间距,直到这些items
均匀地贴合在线条边界内,如图3-3所示。增加间距可以提供items
的整体外观,并防止每条线末端有大间隙。
对于行间距,流式布局对象使用与item
之间的间距相同的技术。如果所有的items
是相同的大小,则流式布局可以绝对地遵守最小行间距值,并且一行中的所有item
与下一行中的items
均匀地间隔开。如果items
的大小不同,则各items
之间的实际间距可能会有所不同。
图3-4显示当items
的大小不同时最小行间距会发生什么变化。对于不同大小的items
, 流式布局对象从每个行中选择在滚动方向上尺寸最大的item
。例如,在垂直滚动的布局中,它在每一行中寻找最大高度的item
。然后,将这些item
之间的间距设置为最小值。如果items
位于行的不同部分,如图所示,实际行间距似乎大于最小值。
与其他流式布局属性一样,可以使用固定间距值或动态变化值。行和item
间隔是逐个处理的。因此,给定分区的所有items
的行和间隔间距相同,但可能在各分区之间变化。可以使用流式布局对象的minimumLineSpacing
和minimumInteritemSpacing
静态地设置间距属性或者使用集合视图代理的collectionView:layout:minimumLineSpacingForSectionAtIndex:
和collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
设置间距属性。
使用分区插图来调整内容的边距
分区插图是可用于调整布局cells
的空间的一种方式。你可以使用插图在分区的头部视图之后和分区的尾部视图之前插入间距。还可以使用插图在内容的两边插入间距。图3-5显示插图如何影响垂直滚动的流式布局中的一些内容。
因为插图减少了可用于布局cells
的空间量,可以使用它们来限制给定行中cell
的数量。在非滚动方向上指定插图是限制每条线的空间的一种方法。如果将该信息与cell
大小相结合,则可以控制每行上的cell
数。
知道何时将流式布局子类化
虽然可以不需要子类化而很有效地使用流式布局,但仍有时候你可能需要子类来获取你需要的行为。表3-1列出了一些需要UICollectionViewFlowLayout
子类实现所需效果的场景。
表3-1 用于子类化UICollectionViewFlowLayout的方案
情节 | 子类化的技巧 |
---|---|
你想要给你的布局添加一个新的补充视图或者装饰视图 | 标准流式布局类支持只有分区头和分区尾并没有装饰的视图。为了支持附加的补充视图和装饰视图,你需要至少重写下列方法:layoutAttributesForElementsInRect: (必须) layoutAttributesForItemAtIndexPath: (必须) layoutAttributesForSupplementaryViewOfKind:atIndexPath: (来支持新的补充视图) layoutAttributesForDecorationViewOfKind:atIndexPath: (来支持新的装饰视图) 在你的layoutAttributesForElementsInRect: 方法中,可以给cell调用super方法来获取布局属性,然后在指定的矩形内给一些新的补充视图或者装饰视图添加这些属性。使用其他方法根据需求提供属性。关于在布局期间为视图提供属性的更多信息,请看Creating Layout Attributes和Providing Layout Attributes for Items in a Given Rectangle. |
你想要调整流式布局返回的布局属性 | 重写layoutAttributesForElementsInRect: 方法和返回布局属性的任何方法。你的方法实现应该调用super,修改父类提供的属性,然后返回它们。 关于深入讨论这些方法所涉及的内容。请看Creating Layout Attributes和Providing Layout Attributes for Items in a Given Rectangle. |
你想要给你的cells和视图添加新的布局属性 | 创建一个UICollectionViewLayoutAttributes 的自定义子类,并添加代表自定义布局信息所需的任何属性。子类化UICollectionViewFlowLayout 并重写layoutAttributesClass 方法,在该方法的实现中,返回你的自定义子类。你应该也重写layoutAttributesForElementsInRect: 方法,layoutAttributesForItemAtIndexPath: 方法,和一些可以返回布局属性其他的方法。在你的自定义实现中,应该给你定义的任何自定义属性设置值。 |
你想要指定要插入或删除的item的初始位置或最终位置 | 默认情况下,会为要插入或删除的item创建一个简单的淡入淡出动画。为了创建自定义动画,你必须重写下面的一些或所有方法:initialLayoutAttributesForAppearingItemAtIndexPath: initialLayoutAttributesForAppearingSupplementaryElementOfKind:atIndexPath: initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath: finalLayoutAttributesForDisappearingItemAtIndexPath: finalLayoutAttributesForDisappearingSupplementaryElementOfKind:atIndexPath: finalLayoutAttributesForDisappearingDecorationElementOfKind:atIndexPath: 在这些方法的实现中,指定要在插入之前或删除之后每个视图具有的属性。流式布局对象会使用你提供的这些属性来执行插入和删除的动画。如果你重写这些方法,那么建议你重写prepareForCollectionViewUpdates: 和finalizeCollectionViewUpdates 方法。你可以使用这些方法来跟踪在当前周期内插入或删除了哪些item。关于如何插入和删除工作的更多信息,请看Making Insertion and Deletion Animations More Interesting
|
还有一些情况下,正确的做法是从头创建一个自定义布局。在决定做这件事之前,花点时间考虑是否真的有必要。流式布局提供了许多适合于不同类型布局的可定制行为,并且因为它提供了,所以易于使用,并包含许多优化以使其高效。然而,这并不是说不应该创建自定义布局,因为在某些情况下这样做绝对有意义。流式布局将滚动方向限制为一个方向,因此如果你的布局包含的内容比屏幕在两个方向上延伸得更远,则自定义布局更有意义。创建一个自定义布局是正确的决定,如果你的布局不是一个网格或线分割的布局,如上所述,如果item在布局中频繁移动,子类化流式布局会比创建自定义布局更复杂。
关于创建自定义布局更多信息,请看Creating Custom Layouts.
官方文档地址
Using the Flow Layout