【问题标题】:UICollectionViewCompositionalLayout, but not a repeating patternUICollectionViewCompositionalLayout,但不是重复模式
【发布时间】:2022-02-12 14:27:15
【问题描述】:

Here is the preview of layout

如您所见,此布局具有相对于大小的单元格 0、1、2、0、1、2、0、1、2 的模式。我希望我的布局将 0、1、2、1、2、1、2、1、2 描绘为相对于大小的模式。 换句话说,只要第一个单元格大,其他单元格就应该占用一个大小以适合 2 的行。 我当前的布局代码:

import UIKit

struct Layout {
    
    private struct LayoutConstants {
        static let largeGroupHeight: CGFloat = 406
        static let leadingInset: CGFloat = 8
        static let topInset: CGFloat = 10
        static let bottomInset: CGFloat = 15
        static let itemCount = 2
        static let fractionalConstant: CGFloat = 1.0
        static let fractionalWidthLeading: CGFloat = 0.67
        static let fractionalWidthTrailing: CGFloat = 1.0
        static let fractionalHeightTrailing: CGFloat = 0.3
        static let fractionalContainerWidth: CGFloat = 1.2
        static let groupFractionalHeight: CGFloat = 0.33
    }
    
    func layoutSection() -> NSCollectionLayoutSection {
        let leadingItem = NSCollectionLayoutItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(LayoutConstants.fractionalWidthLeading),
                heightDimension: .fractionalHeight(LayoutConstants.fractionalConstant)))
        leadingItem.contentInsets = NSDirectionalEdgeInsets(top: LayoutConstants.topInset,
                                                            leading: LayoutConstants.topInset,
                                                            bottom: LayoutConstants.bottomInset,
                                                            trailing: LayoutConstants.leadingInset)
        
        let trailingItem = NSCollectionLayoutItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(LayoutConstants.fractionalWidthTrailing),
                heightDimension: .fractionalHeight(LayoutConstants.fractionalHeightTrailing)))
        trailingItem.contentInsets = NSDirectionalEdgeInsets(top: LayoutConstants.topInset,
                                                             leading: LayoutConstants.leadingInset,
                                                             bottom: LayoutConstants.bottomInset,
                                                             trailing: LayoutConstants.leadingInset)

        let trailingGroup = NSCollectionLayoutGroup.vertical(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(LayoutConstants.groupFractionalHeight),
                heightDimension: .fractionalHeight(LayoutConstants.fractionalConstant)),
            subitem: trailingItem,
            count: LayoutConstants.itemCount)
        
        var subitems: [NSCollectionLayoutItem] = []
        subitems.append(leadingItem)
        subitems.append(trailingGroup)
        
        let containerGroup = NSCollectionLayoutGroup.horizontal(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(LayoutConstants.fractionalContainerWidth),
                heightDimension: .absolute(LayoutConstants.largeGroupHeight)),
            subitems: subitems)
        let section = NSCollectionLayoutSection(group: containerGroup)
        section.orthogonalScrollingBehavior = .continuous
        return section
    }
}

【问题讨论】:

    标签: swift uicollectionview uicollectionviewlayout uicollectionviewflowlayout uicollectionviewcompositionallayout


    【解决方案1】:

    我发现了以下不同的方法:

    1. 我将使用两个部分。
      Section1 为第一个数字,它将包含一个项目的一组。
      对于其他所有内容,Section2 将包含一组两个项目(垂直堆叠)。
    2. 我们需要将集合视图的滚动方向更改为水平
      通常所有部分都是垂直堆叠的,所以这两个部分会垂直堆叠,不会给我们想要的。
    3. 我们需要更改组和项目的布局配置,使其能够在水平滚动方向上正常工作。

    就是这样,现在是代码。

    建议:请尝试逐步从您的解决方案转向我的解决方案,以了解我在测试时学到的不同问题,这将帮助您了解每个部分的原因

    注意:我使用值而不是您的常量,所以它不会让您感到困惑,因为现在需要更改/重命名常量以适应这种方法。

    • Section1(一组一件)
    func createSection1() -> NSCollectionLayoutSection {
        let item = NSCollectionLayoutItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1.0),
                heightDimension: .fractionalHeight(1.0)
            )
        )
        item.contentInsets = NSDirectionalEdgeInsets(
            top: 10,
            leading: 10,
            bottom: 15,
            trailing: 8
        )
        
        let group = NSCollectionLayoutGroup.horizontal(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(0.67),
                heightDimension: .absolute(406)
            ),
            subitem: item,
            count: 1
        )
        
        return NSCollectionLayoutSection(group: group)
    }
    
    • Section2(一组垂直堆叠的两个项目)
    func createSection2() -> NSCollectionLayoutSection {
        
        let item = NSCollectionLayoutItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1.0),
                heightDimension: .fractionalHeight(0.3)
            )
        )
        item.contentInsets = NSDirectionalEdgeInsets(
            top: 10,
            leading: 8,
            bottom: 15,
            trailing: 8
        )
        
        let group = NSCollectionLayoutGroup.vertical(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(0.33),
                heightDimension: .absolute(406)
            ),
            subitem: item,
            count: 2
        )
        
        let section = NSCollectionLayoutSection(group: group)
        return section
    }
    
    • 最终布局
      请注意指示滚动方向更改的行
    func createLayout() -> UICollectionViewLayout {
        let layout = UICollectionViewCompositionalLayout {
            [weak self] (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
            guard let self = self else { return nil }
            
            if sectionIndex == 0 {
                return self.createSection1()
            } else {
                return self.createSection2()
            }
        }
        
        // Changing scrollDirection
        let config = UICollectionViewCompositionalLayoutConfiguration()
        config.scrollDirection = .horizontal
        layout.configuration = config
        
        return layout
    }
    
    • 最后,这里是关于如何在数据源中处理它的建议
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        2
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        data.isEmpty
            ? 0
            : section == 0 ? 1 : data.count - 1
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: String(describing: Cell.self),
            for: indexPath
        ) as! Cell
        
        if indexPath.section == 0 {
            cell.number = data[0]
            cell.color = colors[0]
        } else {
            cell.number = data[indexPath.row + 1]
            cell.color = colors[indexPath.row + 1]
        }
        
        return cell
    }
    
    • 演示

    就是这样,如果您有任何问题,请告诉我。

    【讨论】:

    • 感谢艾哈迈德的解决方案!我有一个我可能错过的细节是我的项目有一个垂直的集合视图,每个部分都有自己的组合布局。此布局是这些部分之一,因此我将无法使用多部分解决方案。不过,我可能会在重构功能时这样做。再次感谢:)
    • @CoderSulemani 嗯,为什么不制作两个单元格,第一个单元格用于此布局,第二个单元格用于其他单元格,然后您将第一个单元格由其自己的 collectionView 组成,并具有两个水平部分的布局。跨度>
    • 是的,我也有同样的想法,希望在重构时能做到这一点。想问这个问题只是为了看看是否有更简单的方法来解决这个问题:)
    • @CoderSulemani 我明白了。根据我目前的理解,部分和项目是物理元素,但组只是描述一些项目如何组织在一个部分中的虚拟元素..所以基本上你只有一个物理元素,命名部分,由一个或多个项目组成,组织在一个或多个组布局中。这就是我开始寻找另一种方法的原因。
    • @CoderSulemani 我还想问你,如果你的场景只是一个大项目,然后是已知数量的垂直堆叠项目,你可以在两个组布局中组织部分中的固定数量的项目.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多