在UICollectionView中将两个部分放在一起

时间:2022-03-04 19:14:00

I have a CollectionView with 6 sections.

我有一个包含6个部分的CollectionView。

The first sections are organised as rows. Section 2 & 3 is where things get difficult. I need to place two sections right next to each other.

第一部分组织为行。第2节和第3节是事情变得困难的地方。我需要将两个部分紧挨着放置。

[................Section 1..............] // one section with a couple of rows
[... Section 2...][...Section 3...] // two sections beneath the first

[................第1节..............] //一节有几排[...第2节。 ..] [...第3节......] //第一节下方的两个部分

I can't divide the second section in two columns because those are different populated with different cells.
Knowing that the flow layout always fills up one section from bounds to bounds, I could only fake such an effect by placing two cells next to each other, which is fine but I add cells and I can only place one beneath the other with an integer which increments each time I create a new cell in cellForItemAtIndexPath: and use it to multiply it by the cell's height.

我不能将第二部分分成两列,因为它们不同,填充了不同的单元格。知道流布局总是从边界到边界填充一个部分,我只能通过将两个单元格放在一起来伪造这样的效果,这很好,但是我添加了单元格,我只能用一个整数放在另一个下面每当我在cellForItemAtIndexPath中创建一个新单元格时,它会递增,并使用它乘以单元格的高度。

The only problem I face then is when I reuse some cells the integer variable hack doesn't work anymore.

我面临的唯一问题是,当我重用一些单元格时,整数变量hack不再起作用。

So is there a better way to, besides a custom layout, which might not do the trick either, to place two sections next to each other?

那么,除了自定义布局之外,还有一种更好的方法可以将两个部分放在一起吗?

thanks in advance

提前致谢

1 个解决方案

#1


1  

You don't necessarily have to write a custom layout, you can actually just subclass UICollectionViewFlowLayout and override a few key methods that determine frame positioning, namely layoutAttributesForElementsInRect:/ layoutAttributesForItemAtIndexPath: where you can check the section and determine positions.

您不一定要编写自定义布局,实际上只需子类化UICollectionViewFlowLayout并覆盖一些确定帧定位的关键方法,即layoutAttributesForElementsInRect:/ layoutAttributesForItemAtIndexPath:您可以在其中检查该部分并确定位置。

The code itself would probably be relatively simple, something along the lines of:

代码本身可能相对简单,类似于:

if indexPath.section == 0 {
    attributes.frame = CGRect(x: 0, y: 0, width: fullWidth, height: someHeight)
} else {
    // Section 2 which is indexed at 1, set the frame
    // to half the width and x to 0
    if indexPath.section %2 != 0 {
        attributes.frame = CGRect(x: 0, y: someYCounter, width: halfWidth, height, someHeight)
    } else {
        attributes.frame = CGRect(x: halfWidth, y: someYCounter, width: halfWidth, height, someHeight)
    }
}

Obviously this is psuedo-code and I haven't run this through a compiler but the essential steps are:

显然这是伪代码,我没有通过编译器运行它,但基本步骤是:

  • have a guard statement that ensures the existence of collection view so you can define the following variables: halfWidth and fullWidth (to be used when laying out later)
  • 有一个保护语句,确保存在集合视图,以便您可以定义以下变量:halfWidth和fullWidth(稍后布局时使用)

  • keep a running counter of your y position
  • 保持你的y位置的运行计数器

  • check the section index and position appropriately
  • 适当检查部分索引和位置

The best way to go about this is to override prepare and calculate an array of layout attributes (and store that as an instance variable). Then in layoutAttributesForItemAtIndexPath: and the like, just return the object at the index in that array (or if the index is for some reason out of bounds, return super.layoutAttributesForItem(at: indexPath).

解决此问题的最佳方法是覆盖prepare并计算布局属性数组(并将其存储为实例变量)。然后在layoutAttributesForItemAtIndexPath:等中,只返回该数组中索引处的对象(或者如果索引由于某种原因超出边界,则返回super.layoutAttributesForItem(at:indexPath)。

That is the beauty of UICollectionViewFlowLayout, most of the heavy lifting is done for you and you can subclass a few simple methods to get the desired behavior. The alternative is a full blown custom layout which, in my opinion, rarely justified unless you have some crazy behavior in which case you should be having conversations with your designers about the complexity of what they make.

这就是UICollectionViewFlowLayout的美妙之处,大部分繁重的工作都是为你完成的,你可以通过几个简单的方法来获得所需的行为。替代方案是一个完整的自定义布局,在我看来,除非你有一些疯狂的行为,否则你应该与你的设计师就他们所做的复杂性进行对话。

#1


1  

You don't necessarily have to write a custom layout, you can actually just subclass UICollectionViewFlowLayout and override a few key methods that determine frame positioning, namely layoutAttributesForElementsInRect:/ layoutAttributesForItemAtIndexPath: where you can check the section and determine positions.

您不一定要编写自定义布局,实际上只需子类化UICollectionViewFlowLayout并覆盖一些确定帧定位的关键方法,即layoutAttributesForElementsInRect:/ layoutAttributesForItemAtIndexPath:您可以在其中检查该部分并确定位置。

The code itself would probably be relatively simple, something along the lines of:

代码本身可能相对简单,类似于:

if indexPath.section == 0 {
    attributes.frame = CGRect(x: 0, y: 0, width: fullWidth, height: someHeight)
} else {
    // Section 2 which is indexed at 1, set the frame
    // to half the width and x to 0
    if indexPath.section %2 != 0 {
        attributes.frame = CGRect(x: 0, y: someYCounter, width: halfWidth, height, someHeight)
    } else {
        attributes.frame = CGRect(x: halfWidth, y: someYCounter, width: halfWidth, height, someHeight)
    }
}

Obviously this is psuedo-code and I haven't run this through a compiler but the essential steps are:

显然这是伪代码,我没有通过编译器运行它,但基本步骤是:

  • have a guard statement that ensures the existence of collection view so you can define the following variables: halfWidth and fullWidth (to be used when laying out later)
  • 有一个保护语句,确保存在集合视图,以便您可以定义以下变量:halfWidth和fullWidth(稍后布局时使用)

  • keep a running counter of your y position
  • 保持你的y位置的运行计数器

  • check the section index and position appropriately
  • 适当检查部分索引和位置

The best way to go about this is to override prepare and calculate an array of layout attributes (and store that as an instance variable). Then in layoutAttributesForItemAtIndexPath: and the like, just return the object at the index in that array (or if the index is for some reason out of bounds, return super.layoutAttributesForItem(at: indexPath).

解决此问题的最佳方法是覆盖prepare并计算布局属性数组(并将其存储为实例变量)。然后在layoutAttributesForItemAtIndexPath:等中,只返回该数组中索引处的对象(或者如果索引由于某种原因超出边界,则返回super.layoutAttributesForItem(at:indexPath)。

That is the beauty of UICollectionViewFlowLayout, most of the heavy lifting is done for you and you can subclass a few simple methods to get the desired behavior. The alternative is a full blown custom layout which, in my opinion, rarely justified unless you have some crazy behavior in which case you should be having conversations with your designers about the complexity of what they make.

这就是UICollectionViewFlowLayout的美妙之处,大部分繁重的工作都是为你完成的,你可以通过几个简单的方法来获得所需的行为。替代方案是一个完整的自定义布局,在我看来,除非你有一些疯狂的行为,否则你应该与你的设计师就他们所做的复杂性进行对话。