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

时间:2013-10-10 16:55:22

标签: ios layout uicollectionview uicollectionviewlayout

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

如何使用UICollectionView及其相关类来完成此操作?我是否必须编写自定义UICollectionViewFlowLayout

12 个答案:

答案 0 :(得分:91)

您是否尝试将UICollectionViewFlowLayout的滚动方向设置为水平?

[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

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

[yourCollectionView setPagingEnabled:YES];

答案 1 :(得分:65)

第一种方法

如何将UIPageViewControllerUICollectionViewControllers数组一起使用呢?您必须在每个UICollectionViewController中获取适当数量的项目,但这应该不难。你会得到与Springboard完全相同的外观。

第二种方法

我已经考虑过这一点,在我看来你必须设置:

self.collectionView.pagingEnabled = YES;

并通过继承UICollectionViewLayout创建自己的集合视图布局。从自定义布局对象中,您可以访问self.collectionView,这样您就可以知道集合视图{@ 1}},framenumberOfSections的大小。根据该信息,您可以计算单元格numberOfItemsInSection:frames)和prepareLayout。这里有一些关于创建自定义布局的文章:

第3种方法

您可以在不创建自定义布局的情况下执行此操作(或其近似值)。在空白视图中添加collectionViewContentSize,在其中启用分页。在滚动视图中添加集合视图。然后为其添加宽度约束,检入代码中包含的项目数量,并将其UIScrollView设置为正确的值,例如constant。以下是它的外观(单元格上的数字显示(self.view.frame.size.width * numOfScreens)):https://www.dropbox.com/s/ss4jdbvr511azxz/collection_view.mov如果您对单元格的排序方式不满意,那么我担心您必须使用1.或者2。

答案 2 :(得分:29)

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

enter image description here

答案 3 :(得分:11)

如果您在代码中定义UICollectionViewFlowLayout,它将覆盖Interface Builder配置。因此,您需要再次重新定义scrollDirection

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

答案 4 :(得分:8)

只是为了好玩,另一种方法是离开分页和水平滚动设置,添加一个方法来改变数组项的顺序,从“从上到下,从左到右”转换为 visual < / strong>'从左到右,从上到下'并用空的隐藏单元格填充中间单元格以使间距正确。如果网格中的7个项目为9,则可能如下所示:

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

应该成为

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

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

它在我构建的音板应用程序中运行良好,所以如果有人想要工作代码,我会添加它。只需要很少的代码就可以使这个技巧发挥作用,听起来比它更难!

<强>更新

我怀疑这是最好的解决方案,但请求此处的工作代码:

- (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中使用的相同转化来获取相应的项目。如果您有单元格边距,则需要将它们添加到行和列计算中,因为这些必须正确才能使其正常工作。

答案 5 :(得分:7)

此代码适用于 Swift 3.1 Xcode 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()
        }

    }

答案 6 :(得分:6)

我正在使用Xcode 6.2,而对于水平滚动,我在属性检查器中更改了滚动方向。

点击collectionView-&gt;属性检查器 - &gt;滚动方向 - >更改为水平

enter image description here我希望它有所帮助。

答案 7 :(得分:6)

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

我使用&#34; SMCollectionViewFillLayout&#34;

的自定义布局类实现实现了它

代码存储库:

https://github.com/smindia1988/SMCollectionViewFillLayout

输出如下:

<强> 1.png

First.png

<强> 2_Code_H-Scroll_V-Fill.png

enter image description here

<强> 3_Output_H-Scroll_V-Fill.png enter image description here

<强> 4_Code_H-Scroll_H-Fill.png enter image description here

<强> 5_Output_H-Scroll_H-Fill.png enter image description here

答案 8 :(得分:6)

对于xcode 8我做了这个并且它有效:

答案 9 :(得分:5)

来自@Erik Hunter,我发布了make horizo​​ntal 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

希望这个帮助

答案 10 :(得分:1)

您可以编写自定义pymysql.err.InternalError: (1366, "Incorrect string value: '\\xF0\\x9F\\x87\\xBA\\xF0\\x9F...' for column 'Message' at row 1") 布局来实现此目的,这是我的实现的演示图像:

demo image

此处的代码存储库:KSTCollectionViewPageHorizontalLayout

@iPhoneDev(这也许对你有帮助)

答案 11 :(得分:0)

如果需要设置UICollectionView滚动“方向水平”,并且需要将单元格的宽度和高度设置为静态。 请将收藏视图的估算大小自动设置为

View The ScreenShot