UICollectionView – 水平滚动,水平布局?

我有一个UIScrollView,列出了一个图标的网格。 如果你想象iOS跳板的布局,你会非常接近正确的。 它有一个水平的页面滚动(就像跳板)。 但是,看起来布局不太正确。 看起来好像是从上到下布置项目。 因此,由于要显示的项目数量,我的最后一列只有2行。 我宁愿让最后一页的最后一行有两个项目,就像你在Springboard中看到的一样。

这怎么可以用UICollectionView和它的相关类来完成? 我必须编写一个自定义的UICollectionViewFlowLayout吗?

第一种方法

使用UIPageViewControllerUICollectionViewControllers数组UICollectionViewControllers样? 您必须在每个UICollectionViewController获取适当数量的项目,但不应该很难。 你会得到与Springboard完全一样的外观。

第二种方法

我想过这个,在我看来你必须设定:

 self.collectionView.pagingEnabled = YES; 

并通过UICollectionViewLayout创build自己的集合视图布局。 从自定义布局对象中,你可以访问self.collectionView ,所以你会知道集合视图的frame的大小是什么, numberOfSectionsnumberOfItemsInSection: 有了这些信息,你可以计算单元格的frames (在prepareLayout )和collectionViewContentSize 。 这里有一些关于创build自定义布局的文章:

第三种方法

您可以在不创build自定义布局的情况下(或近似)执行此操作。 在空白视图中添加UIScrollView在其中设置分页。 在滚动视图中添加一个集合视图。 然后添加一个宽度约束,检查代码中有多less项,并将其constant设置为正确的值,例如(self.view.frame.size.width * numOfScreens) 。 以下是它的外观(单元格中的数字显示indexPath.row ): https : indexPath.row如果您对单元格的排列方式不满意,那么恐怕你必须去1或2。

你有没有尝试将UICollectionViewFlowLayout的滚动方向设置为水平?

 [yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; 

如果你想要像跳板这样的页面,你需要在你的集合视图上启用分页,如下所示:

 [yourCollectionView setPagingEnabled:YES]; 

您需要将UICollectionView的高度降低到其单元格/项目高度,并从“ Scroll Direction ”中select“ Horizontal ”,如下面的截图所示。 然后它将水平滚动,取决于您在其数据源实现中返回的numberOfItems

在这里输入图像说明

只是为了好玩,另一种方法是只保留分页和水平滚动设置,添加一个方法,改变数组项目的顺序,从“从上到下,从左到右”转换为视觉上的从左到右,从上到下底部“,并用空的隐藏单元填充中间单元格,以使间距正确。 如果9个网格中的7个项目,这将是这样的:

 [1][4][7] [2][5][ ] [3][6][ ] 

应该成为

 [1][2][3] [4][5][6] [7][ ][ ] 

所以1 = 1,2 = 4,3 = 7等,6 =空。 您可以通过计算行和列的总数来对它们重新sorting,然后计算每个单元格的行和列号,更改列的行,反之亦然,然后获得新的索引。 当单元格没有与图像对应的值时,可以返回空单元格并设置cell.hidden = YES; 到它。

它在我创build的音板应用程序中工作得很好,所以如果有人想要工作代码,我会添加它。 只需要很less的代码来使这个技巧工作,这听起来比它更难!

更新

我怀疑这是最好的解决scheme,但通过请求这里的工作代码:

 - (void)viewDidLoad { // Fill an `NSArray` with items in normal order items = [NSMutableArray arrayWithObjects: [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 1", @"label", @"Some value 1", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 2", @"label", @"Some value 2", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 3", @"label", @"Some value 3", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 4", @"label", @"Some value 4", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 5", @"label", @"Some value 5", @"value", nil], nil ]; // Calculate number of rows and columns based on width and height of the `UICollectionView` and individual cells (you might have to add margins to the equation based on your setup!) CGFloat w = myCollectionView.frame.size.width; CGFloat h = myCollectionView.frame.size.height; rows = floor(h / cellHeight); columns = floor(w / cellWidth); } // Calculate number of sections - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return ceil((float)items.count / (float)(rows * columns)); } // Every section has to have every cell filled, as we need to add empty cells as well to correct the spacing - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return rows*columns; } // And now the most important one - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier@"myIdentifier" forIndexPath:indexPath]; // Convert rows and columns int row = indexPath.row % rows; int col = floor(indexPath.row / rows); // Calculate the new index in the `NSArray` int newIndex = ((int)indexPath.section * rows * columns) + col + row * columns; // If the newIndex is within the range of the items array we show the cell, if not we hide it if(newIndex < items.count) { NSDictionary *item = [items objectAtIndex:newIndex]; cell.label.text = [item objectForKey:@"label"]; cell.hidden = NO; } else { cell.hidden = YES; } return cell; } 

如果您想使用didSelectItemAtIndexPath方法,则必须使用与cellForItemAtIndexPath使用的转换相同的转换来获取相应的项目。 如果您有单元格边距,则需要将它们添加到行和列计算中,因为这些必须是正确的才能使其工作。

我正在使用Xcode 6.2和水平滚动我已经改变属性检查器中的滚动方向。

点击collectionView->属性inspector->滚动Direction->改变为水平

在这里输入图像说明 我希望它可以帮助别人。

如果在代码中定义了UICollectionViewFlowLayout ,它将覆盖Interface Builder的configuration。 因此你需要重新定义scrollDirection

 let layout = UICollectionViewFlowLayout() ... layout.scrollDirection = .Horizontal self.awesomeCollectionView.collectionViewLayout = layout 

从@Erik Hunter,我发布完整的代码,使水平的UICollectionView

 UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init]; [collectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; self.myCollectionView.collectionViewLayout = collectionViewFlowLayout; 

在Swift中

 let layout = UICollectionViewFlowLayout() layout.scrollDirection = .Horizontal self.myCollectionView.collectionViewLayout = layout 

在Swift 3.0中

 let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal self.myCollectionView.collectionViewLayout = layout 

希望这个帮助

我们可以使用UICollectionView做同样的Springboard行为,为此我们需要编写自定义布局的代码。

我已经实现了与我的自定义布局类实现“SMCollectionViewFillLayout”

代码库:

https://github.com/smindia1988/SMCollectionViewFillLayout

输出如下:

1.png

First.png

2_Code_H-Scroll_V-Fill.png

在这里输入图像说明

3_Output_H-Scroll_V-Fill.png 在这里输入图像说明

4_Code_H-Scroll_H-Fill.png 在这里输入图像说明

5_Output_H-Scroll_H-Fill.png 在这里输入图像说明

这段代码在Swift 3.1Xcode 8.3.2中运行良好

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal self.collectionView.collectionViewLayout = layout self.collectionView!.contentInset = UIEdgeInsets(top: -10, left: 0, bottom:0, right: 0) if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout { layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 0 layout.itemSize = CGSize(width: self.view.frame.size.width-40, height: self.collectionView.frame.size.height-10) layout.invalidateLayout() } } 

为Xcode 8我做到了这一点,它的工作原理:

你可以写一个自定义的UICollectionView布局来实现这一点,这里是我的实现的演示图像:

demo image

这是代码库: KSTCollectionViewPageHorizo​​ntalLayout

@iPhoneDev(这也许可以帮助你)