为什么我的单部分、2 组构图布局仅使用该部分中第一组的大小?

问题描述 投票:0回答:1

我正在尝试创建一个由一组 2 个项目和另一组 1 个项目组成的组合布局。我希望每个组都占据整个屏幕宽度,并在它们之间进行页面滚动。因此,第一组中的 2 个项目(项目 A)将各自占据屏幕宽度的 50%,第二组中的 1 个项目(项目 B)将占据屏幕宽度的 100%。我将集合视图固定在其超级视图的左右边缘,它占据了整个屏幕。

文本图会显示如下:

[Item A][Item A]|[    Item B    ]

“|”在哪里表示屏幕的边缘。因此,根据滚动位置,要么项目 A 都可见,要么项目 B 都可见。滚动结束后,项目 A 和项目 B 永远不应该同时可见。

我使用以下代码进行构图布局:

UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))

    let planItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1))
    let planItem = NSCollectionLayoutItem(layoutSize: planItemSize)
    let planGroup = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: planItem, count: 2)

    let formItem = NSCollectionLayoutItem(layoutSize: groupSize)
    let formGroup = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: formItem, count: 1)

    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [planGroup, formGroup])
    let section = NSCollectionLayoutSection(group: group)
    section.orthogonalScrollingBehavior = .groupPaging
    return section
}

上面的代码产生的布局如下所示:

[Item A][Item A]|[Item B]

除了项目 B 的大小设置为屏幕宽度的 50% 而不是 100% 之外,它几乎是正确的。我不知道布局出了什么问题,但它似乎对所有项目都使用

planItemSize
,而不仅仅是项目 A。如何使项目 B 的大小达到屏幕宽度的 100%?

ios swift uicollectionview uikit uicollectionviewcompositionallayout
1个回答
0
投票

首先,我们可以使用水平流布局

.isPagingEnabled = true
并实现
sizeForItemAt
:

轻松地做到这一点
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let w: CGFloat = collectionView.frame.width
    let h: CGFloat = collectionView.frame.height

    if indexPath.item % 3 == 2 {
        return .init(width: w, height: h)
    }
    
    return .init(width: w * 0.5, height: h)
    
}

我们就完成了:)

但是,既然你问的是

UICollectionViewCompositionalLayout
,那我们就来看看吧。

使用 itemsgroupssub-groups 时,

.fractionalWidth()
.fractionalHeight()
相对于 parent

由于我们在此布局中的所有高度都使用

100%
,因此我们将重点关注宽度。

对于“基本”布局,

.fractionalWidth(1.0)
将是集合视图宽度的 100%。

使用

.fractionalWidth(0.5)
当然,将是集合视图宽度的 50%。

当我们将项目放入中时,

count:
会影响大小,并且项目宽度(显然)会被忽略。

因此,如果我们将组设置为

.fractionalWidth(1.0)
(集合视图宽度的100%),并将计数设置为4:

let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1))
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 4)
let section = NSCollectionLayoutSection(group: group)
return section

我们会得到这个(红色轮廓是集合视图框架):

我们可以将

itemSize
.fractionalWidth(1.0)
更改为
0.1
0.5
2.0
等...它不会改变布局。

在当前代码中,您将

planGroup
formGroup
设置为其父级的
100%
宽度 -
group
- 也是集合视图宽度的
100%

因此,只有first组适合,而第二组永远不会被使用。

(我要把

group
改为
mainGroup
以便更容易谈论。)

我们可以做的是将

planGroup
设置为
.fractionalWidth(0.5)
并将
formGroup
设置为
.fractionalWidth(0.5)
...我们就会接近:

但是 - 我们如何让两个项目填充集合视图,然后是一个项目,然后是两个项目,等等?

我们可以将

mainGroup
宽度设置为集合视图宽度的 200%

现在我们得到了想要的“模式”。请注意,我们需要使用

.paging
而不是
.groupPaging
,因为我们想要按集合视图宽度进行分页:

这是代码的修改版本 - 您应该能够将其直接作为替换:

    UICollectionViewCompositionalLayout {
        (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
        
        // main group size is TWICE as wide as the collection view
        let mainGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(2.0), heightDimension: .fractionalHeight(1))
        
        // sub-groups
        //  width is Percentage-of-Parent
        //  so if each sub-group is one-half the width of the main group
        //  each will be the Full width of the collection view
        let planGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1))
        let formGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1))
        
        // because we're putting TWO planItems in planGroup
        //  CompositionLayout will use 50% of planGroup width for each item
        //  so planItemSize width is ignored
        let planItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1))
        let planItem = NSCollectionLayoutItem(layoutSize: planItemSize)
        let planGroup = NSCollectionLayoutGroup.horizontal(layoutSize: planGroupSize, subitem: planItem, count: 2)
        
        // because we're putting ONE formItem in formGroup
        //  CompositionLayout will use 100% of formGroup width
        //  so formItemSize width is ignored
        let formItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1))
        let formItem = NSCollectionLayoutItem(layoutSize: formItemSize)
        let formGroup = NSCollectionLayoutGroup.horizontal(layoutSize: formGroupSize, subitem: formItem, count: 1)
        
        let mainGroup = NSCollectionLayoutGroup.horizontal(layoutSize: mainGroupSize, subitems: [planGroup, formGroup])
        let section = NSCollectionLayoutSection(group: mainGroup)
        
        // use .paging instead of .groupPaging
        //  because we want to page by collection view Width
        section.orthogonalScrollingBehavior = .paging
        
        return section
        
    }
© www.soinside.com 2019 - 2024. All rights reserved.