首页 > 解决方案 > StackView 中的多个 CollectionView

问题描述

我目前有几个使用组合布局的集合视图,我试图将它们添加到两个独立的垂直堆栈视图中。我的一个集合视图将进入 headerContentView,另一个将进入实际的 contentView。

我的 collectionView 应该通过使内在内容大小无效来自行调整大小。但是,由于某种原因,只有一个 collectionView 是可见的,因为它会将自身调整为内容大小。但是,另一个的高度将为 0。请注意,包含第二个 collectionView 的堆栈视图的高度也为零。

我需要帮助才能正确调整集合视图的大小。 谢谢你的时间。

堆栈视图:
internal let contentStackView: UIStackView = {
    let stackView = UIStackView()
    stackView.axis = .vertical
    return stackView
}()
StackView 上的约束:
private func setUpView() {
    backgroundColor = .blue
    layoutMargins = UIEdgeInsets(top: 0, left: 16, bottom: 24, right: 16)

    addSubview(headerView)
    addSubview(contentStackView)

    // Preserve superview layout margins so that sub-elements can be laid out using layoutMarginsGuide
    contentStackView.preservesSuperviewLayoutMargins = true

    [headerView, contentStackView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false }
    NSLayoutConstraint.activate([
        headerView.topAnchor.constraint(equalTo: topAnchor),
        contentStackView.topAnchor.constraint(equalTo: headerView.bottomAnchor, constant: 16),
        layoutMarginsGuide.bottomAnchor.constraint(lessThanOrEqualTo: contentStackView.bottomAnchor),

        headerView.leadingAnchor.constraint(equalTo: leadingAnchor),
        headerView.trailingAnchor.constraint(equalTo: trailingAnchor),
        contentStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
        contentStackView.trailingAnchor.constraint(equalTo: trailingAnchor)
    ])
}

private func setUpHeaderView() {
    // Preserve superview layout margins so that sub-elements can be laid out using layoutMarginsGuide
    headerView.preservesSuperviewLayoutMargins = true
    headerContentStackView.preservesSuperviewLayoutMargins = true
    headerView.addSubview(headerContentStackView)

    headerContentStackView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        headerContentStackView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
        headerView.bottomAnchor.constraint(lessThanOrEqualTo: headerContentStackView.bottomAnchor),

        headerContentStackView.leadingAnchor.constraint(equalTo: headerView.leadingAnchor),
        headerContentStackView.trailingAnchor.constraint(equalTo: headerView.trailingAnchor)
    ])

    // Add header contents to header content stack view
    headerContentStackView.addArrangedSubview(headerBarView)
    headerContentStackView.addArrangedSubview(notificationView)
}
组成布局:
 private static func generateCompositionalLayout() -> UICollectionViewLayout {
    // Items
    let itemSize: NSCollectionLayoutSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(UIConstantsIconTileCollectionView.PhaseTwo.fractionalWidthForItems),
        heightDimension: .fractionalHeight(UIConstantsIconTileCollectionView.PhaseTwo.fullWidthOrHeight)
    )
    let fullItem: NSCollectionLayoutItem = NSCollectionLayoutItem(layoutSize: itemSize)

    // Groups
    let groupSize: NSCollectionLayoutSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(UIConstantsIconTileCollectionView.PhaseTwo.fullWidthOrHeight),
        heightDimension: .fractionalWidth(UIConstantsIconTileCollectionView.PhaseTwo.fractionalWidthForGroups)
    )
    let group: NSCollectionLayoutGroup = NSCollectionLayoutGroup.horizontal(
        layoutSize: groupSize,
        subitem: fullItem,
        count: UIConstantsIconTileCollectionView.PhaseTwo.numberOfItemsPerGroup
    )
    group.interItemSpacing = .fixed(UIConstantsIconTileCollectionView.PhaseTwo.interGroupSpacing)

    // Section
    let section: NSCollectionLayoutSection = NSCollectionLayoutSection(group: group)
    section.contentInsets = NSDirectionalEdgeInsets(
        top: 0,
        leading: UIConstantsIconTileCollectionView.PhaseTwo.interSectionSpacing,
        bottom: 0,
        trailing: UIConstantsIconTileCollectionView.PhaseTwo.interSectionSpacing
    )

    return UICollectionViewCompositionalLayout(section: section)
}
自选尺寸系列视图:
// MARK: - View Layout
override var contentSize: CGSize {
    didSet {
        invalidateIntrinsicContentSize()
    }
}

override var intrinsicContentSize: CGSize {
    return contentSize
}

标签: ioscollectionviewstackview

解决方案


我的解决方案是我实现 CollectionViewController 的方式。我正在覆盖 loadView() 并用 collectionView 替换视图本身。示例,如下:

override func loadView() {
     view = collectionView
}

但是,当我覆盖 viewDidLoad 并将 collectionView 添加为子视图并将其约束到视图控制器视图时,它工作得很好。示例,如下:

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(collectionView)
    // Constraint collectionView -> view
}

我找不到为什么这与 stackViews 配合得更好,因为它让我大吃一惊,但这解决了这个问题。如果有人对为什么基本上只有一个 collectionView 的容器视图与 stackView 配合得很好有更多的知识,我将不胜感激。


推荐阅读