理解 UICollection Flow Layout 流式布局
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解 UICollection Flow Layout 流式布局相关的知识,希望对你有一定的参考价值。
参考技术AUICollectionView 因为 流式布局 (flow layout)而成了为一个非常强大的 UI 组件,流式布局是一种动态网格,提供了 table view 所不具备的功能。
flow layout 实际上是 layout 的子类。(普通的)layout 要更强大一点,因为你可以任意布局单元格!环形布局?没问题!
但在本文中,我们只讨论垂直的流式布局。
有两种实现方式:
在讨论如何实现上面的方法之前,先搞懂单元格是如何被布局的。
用垂直的流式布局作为例子(水平的很相似)。
如果单元格具有固定的大小,只要使用 layout 对象即可—— [UICollectionViewFlowLayout](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionViewFlowLayout_class/index.html#//apple_ref/occ/instp/UICollectionViewFlowLayout/)
这是单元格为 100x100 的例子,相隔 至少 8pt,section inset 也为 8pt。
如果单元格很简单,布局就这么简单。
如果单元格有不同的尺寸,就需要用高级方法了,要实现 [UICollectionViewDelegateFlowLayout](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionViewDelegateFlowLayout_protocol/#//apple_ref/occ/intfm/UICollectionViewDelegateFlowLayout/) 。
使用了相同的 UICollectionViewFlowLayout 对象,但会实现它的代理方法以定制更高级的功能。
举个例子,如果每个单元格尺寸不同,会实现如下方法:
对于最小行间距、单元格间距等等都有对应的代理方法。
这些都是可选的,如果不实现它们,就会直接使用流式布局对象的属性。
一个 常见问题 是要让单元格有 固定的间距 。
然而,只能设置 minimumInteritemSpacing ,实际单元格间距由 collection view 的宽度决定。
UICollectionViewFlowLayout 会在应用 section inset 后排列中间的单元格,每个单元格之间的间距都相同。
如果想要固定的间距, 这么做 可以实现,通过修改 section 的左右 inset:
流式布局是开箱即用的。易于使用,对于大多数 UI 都足够了。
但也可以创建自己的 自定义布局 。
布局类的核心方法是 layoutAttributesForElementsInRect: 。可以读一下 来自 objc.io 的教程,写的很好。这是更高级别的主题。
注意: 通常我们会使用 autolayout 约束,但对于单元格(cell),需要用传统的方式设置 frame。只有 cell 要这么做。单元格里面的视图仍然可以使用自动布局。
UICollection 的镜像滚动
【中文标题】UICollection 的镜像滚动【英文标题】:Mirror scrolling of UICollection 【发布时间】:2013-04-10 05:32:47 【问题描述】:我创建了一个具有自定义布局的 UICollection,以允许垂直和水平滚动。它是一个由相等部分和每个部分中的项目组成的网格(即 10 x 10、20 x 20 等)。我希望能够放置两个仍然可见的标题,一个在顶部,一个在左侧。我还没有找到在 UICollection 本身中执行此操作的方法。因此,我在左侧设置了 UICollection,在顶部设置了另一个。但是,当用户左右和/或上下滚动网格时,我希望这两个集合能够反映这些移动。
所以,我的问题是:有没有办法将主 UICollection 的水平移动镜像到顶部 UICollection,然后将主 UICollection 的垂直移动镜像到侧面 UICollection?
谢谢!
【问题讨论】:
【参考方案1】:UICollectionView
是UIScrollView
的子类。它向其委托发送UIScrollViewDelegate
protocol 中定义的所有消息。
您要回复的消息是scrollViewDidScroll:
。当您的主集合视图发送此消息时,您希望通过获取其contentOffset
并将偏移量应用于您的边距集合视图来响应它。
// Implement this in your main collection view's delegate.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
[self synchronizeCollectionViewContentOffsets];
- (void)synchronizeCollectionViewContentOffsets
CGPoint offset = self.mainCollectionView.contentOffset;
self.leftMarginView.contentOffset = CGPointMake(0, offset.y);
self.topMarginView.contentOffset = CGPointMake(offset.x, 0);
【讨论】:
当视图首次显示时,它会自动滚动到主 UICollectionView 中的特定单元格,这确实会触发 scrollViewDidScroll 方法,然后触发 synchronize 方法;然而,在第一行创建的偏移点基本上是 0,0,即使它滚动到的点甚至不接近那个点。当我尝试滚动网格时也是这种情况。创建的偏移点始终为 1.343243x-34 或类似的值。【参考方案2】:所以,我想通了。使用 self.mainCollectionView.contentOffset 总是返回 (0,0),所以尝试使用我通过 Storyboard 和视图控制器实际分配给它的对象名称。这行得通。
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
[self synchronizeCollectionViewContentOffsets];
-(void)synchronizeCollectionViewContentOffsets
CGPoint offset = myCollectionView.contentOffset;
myLeftMargin.contentOffset = CGPointMake(0, offset.y);
myTopMargin.contentOffset = CGPointMake(offset.x, 0);
myCollectionView、myLeftMargin 和 myTopMargin 通过 Storyboard 链接到 UICollectionView。
【讨论】:
以上是关于理解 UICollection Flow Layout 流式布局的主要内容,如果未能解决你的问题,请参考以下文章
在单独的 UICollection 类中使用未解析的标识符“UICollection”