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

Sha*_*man 57 layout ios uicollectionview uicollectionviewlayout

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

如何通过UICollectionView及其相关课程来实现这一目标?我必须写一个自定义UICollectionViewFlowLayout

Eri*_*ter 91

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

[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
Run Code Online (Sandbox Code Playgroud)

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

[yourCollectionView setPagingEnabled:YES];
Run Code Online (Sandbox Code Playgroud)

  • 是的,但正如我在问题中所提到的,这会在每个页面上从上到下填充集合视图.因此,最后一列仅部分填充.我宁愿它从左到右填充集合视图,留下最后一行部分填充. (9认同)

Are*_*lko 69

第一种方法

使用UIPageViewController数组UICollectionViewControllers怎么样?你必须在每个项目中获取适当数量的项目UICollectionViewController,但这应该不难.你会得到与Springboard完全相同的外观.

第二种方法

我考虑过这个,在我看来你必须设置:

self.collectionView.pagingEnabled = YES;
Run Code Online (Sandbox Code Playgroud)

并通过子类创建自己的集合视图布局UICollectionViewLayout.从您可以访问的自定义布局对象self.collectionView,您将知道集合视图的大小frame,numberOfSections以及numberOfItemsInSection:.使用该信息,您可以计算单元格frames(in prepareLayout)和collectionViewContentSize.这里有一些关于创建自定义布局的文章:

第三种方法

您可以在不创建自定义布局的情况下执行此操作(或其近似值).添加UIScrollView空白视图,在其中启用分页.在滚动视图中添加集合视图.然后添加一个宽度约束,检入代码中有多少项,并将其设置constant为正确的值,例如(self.view.frame.size.width * numOfScreens).这是它的外观(单元格上的数字显示indexPath.row):https://www.dropbox.com/s/ss4jdbvr511azxz/collection_view.mov如果你对细胞的订购方式不满意,那我恐怕你会必须与1.或2.


Dee*_*kur 35

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

在此输入图像描述

  • 但这并没有回答这个问题. (2认同)
  • 谢谢"你需要将UICollectionView的高度降低到它的单元格/项目高度"这个技巧对我来说非常有用. (2认同)

Daz*_*ong 13

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

let layout = UICollectionViewFlowLayout()
...
layout.scrollDirection = .Horizontal
self.awesomeCollectionView.collectionViewLayout = layout
Run Code Online (Sandbox Code Playgroud)


Tum*_*Tum 8

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

[1][4][7]
[2][5][ ]
[3][6][ ]
Run Code Online (Sandbox Code Playgroud)

应该成为

[1][2][3]
[4][5][6]
[7][ ][ ]
Run Code Online (Sandbox Code Playgroud)

所以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;
}
Run Code Online (Sandbox Code Playgroud)

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


Pra*_*wad 8

此代码在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()
        }

    }
Run Code Online (Sandbox Code Playgroud)

  • 在将其分配给集合视图之前,为什么不设置布局的这些属性? - 它会更清洁. (3认同)

Nar*_*tty 6

我正在研究Xcode 6.2,对于水平滚动,我在属性检查器中更改了滚动方向.

单击collectionView->属性检查器 - >滚动方向 - >更改为水平

在此输入图像描述 我希望它对某人有帮助.


Pha*_*inh 6

来自@Erik Hunter,我发布了make horizo​​ntal的完整代码 UICollectionView

UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[collectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.myCollectionView.collectionViewLayout = collectionViewFlowLayout;
Run Code Online (Sandbox Code Playgroud)

在斯威夫特

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .Horizontal
self.myCollectionView.collectionViewLayout = layout
Run Code Online (Sandbox Code Playgroud)

在Swift 3.0中

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
self.myCollectionView.collectionViewLayout = layout
Run Code Online (Sandbox Code Playgroud)

希望这有帮助

  • 我在viewDidLoad()中添加了代码.谢谢:-) (2认同)

San*_* SM 6

我们可以使用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 在此输入图像描述

  • @Sandy我知道OP没有要求这个,但是你有没有机会在Swift中使用你的代码? (2认同)

Gul*_*ulz 6

对于xcode 8,我做到了,它的工作原理是: