UICollectionView可以在水平和垂直方向上滚动

23

我使用了 UICollectionView 来实现垂直滚动。

Cell 的宽度大于屏幕宽度,因此我创建了一个基于 UICollectionViewFlow 布局的 customFlowLayout ,返回正确计算的内容大小。

然而,这并不起作用。当单元格宽度小于屏幕宽度时,它可以正常工作。这是否意味着在垂直滚动中我们不能拥有大于屏幕宽度的宽度?

对于水平滚动也是一样的情况,但此时 CollectionView 的高度受限于屏幕高度。

有没有办法使其正常工作?


1
最近我不得不重新审视它。我创建了一个演示项目,托管在这里:https://github.com/izotx/ScrollableCollectionView 它使用嵌入在滚动视图中的集合视图来双向滚动内容。希望你会发现它有用。 - Janusz Chudzynski
5个回答

15

就像其他人已经说过的,UICollectionView只能使用流式布局在一个方向上滚动。然而,你可以非常容易地实现这一点,而不需要创建自定义布局或使用第三方库。

当你在story board中布置视图时,可以将你的UICollectionView嵌入到一个UIScrollView中。将滚动视图设置为水平滚动,而UICollectionView则垂直滚动。然后将UICollectionView.delaysContentTouches设置为true,这样触摸事件将通过到达UIScrollView,而不会认为你要滚动collectionview。

在设置UICollectionView时,将其大小和单元格的大小设置为实际想要的尺寸(比实际屏幕宽),并相应地布置它们。

现在,在包含的UIViewController中,在视图生命周期内加入以下代码:

    - (void)viewDidLayoutSubviews {
        self.myScrollView.contentSize = self.myCollectionView.frame.size;
    }

这就是你要做的全部,以实现你所描述的功能。现在你的滚动视图应该允许你水平滚动以查看整个单元格,而你的集合视图应该垂直滚动浏览所有单元格。

祝你编程愉快。


11
这个方法对我很有效,但要注意:这种布局会强制CollectionView一次性生成所有的单元格,所以在有大量单元格时,这种解决方案是不实际的。由于我的CollectionView非常大,最终我需要找到另一种解决方案(https://dev59.com/dGUp5IYBdhLWcg3wEETd)。 - Nerrolken
1
@AlexanderWinn,感谢您的反馈。提供的解决方案非常好。在这个特定的问题中,实际上您不需要加载比所需更多的单元格。我在一个可连续滚动的日历周(垂直小时)中使用它。因此,它具有潜在的无限单元格,并且根据需要加载它们。提供的解决方案适用于具有行和列的集合视图,在该视图中需要同时水平和垂直滚动(处于一种缩放状态)。而这个问题更具体地针对单行集合视图,其中每个单独的单元格都比可见屏幕大。不过,您的澄清很好。 - johnrechd
1
我应该在哪里添加延迟内容触摸? - johnny
1
@johnny - 如果你在使用storyboard或xib,那么可能是在viewDidLoad方法中。 - johnrechd
@Nerrolken,不知道为什么它会强制CV一次性加载所有单元格? - stonedauwg

1

在进行此操作之前,您必须使用不同类型的布局。流式布局将其项目表示为列表,并根据可用宽度在单元格中跨越这些项目。 如果您想同时拥有水平和垂直滚动,您需要以某种方式指定网格的列数。FlowLayout没有这个功能。一个简单的解决方案是创建UICollectionViewLayout的子类,并覆盖collectionViewContentSize以使其返回一个宽度=一行单元格宽度的总和(这就是需要知道要多少列的地方),加上它们之间的任何额外间距。如果您的单元格每列具有相同的大小,类似于网格,则此方法将有效。


0

我不确定我是否理解了你的问题。

但是,如果您已经制作了自定义布局,请确保已经实现了:

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

同时确保您的布局属性框架和大小已经为“大型单元格”索引路径设置了正确的值。

另外,请确保您已经实现了:

- (CGSize) collectionViewContentSize;

该方法返回集合视图的contentSize。如果contentSize.width > 你的AppFrame.width,则应该进行水平滚动。高度也是一样,适用于垂直滚动。

还要确保你的collectionView允许滚动,并且使用以下方式正确准备你的布局:

- (void)prepareLayout

顺便问一下,你的布局是重载了 UICollectionViewLayout 还是 UICollectionViewFlowLayout

我正在对UICollectionViewFlowLayout进行子类化...我已经指定了collectionViewContentSize。在preparelayout中,我设置了itemsize [self setItemSize:CGSizeMake(10.0f*200.0f, 30)]; 我的要求是,单元格宽度超过屏幕宽度,并且行数超过屏幕高度。我不知道如何使用uicollectionview实现这一点... - last-Programmer

0

Xcode 11+,Swift 5。

我解决了我的问题,我准备好了视频代码


0
你应该将UITableView嵌入到UIScrollView中。 ScrollView和TableView的高度相同,但宽度不同。 这样UITableView就可以垂直滚动,UIScrollView就可以水平滚动。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接