UIScrollView 无法识别 UICollectionView 的内容大小

UIScrollView Not Recognizing UICollectionView's Content Size

我有这个自定义的 UIScrollView,我已经将其限制在超级视图中,它包含一个名为 'contentView' 的 UIView,我将其固定到 UIScrollView 的所有边缘。然后,我将包含 2 个 UIView 和一个 UICollectionView 的 UIView 添加到此 'contentView',它位于自定义 UIScrollView 的 class 中。从这里我开始像往常一样设置约束。所有这些都是以编程方式完成的。

2个UIView正确显示,但collectionView不正确。它甚至不显示。我将 collectionView 的约束设置为 'contentView' 的所有边缘。我没有设置高度,因为我希望它基于 collectionView 的 contentSize。

这是自定义的 UIScrollView class:

import UIKit
import PureLayout
class ContentScrollView: UIScrollView {
    enum Direction {
        case vertical
        case horizontal
    }
    lazy var contentView: UIView = {
        let view = UIView()
        return view
    }()
    let direction: Direction
    private var didSetupConstraints = false
    // MARK: - Init
    override init(frame: CGRect) {
        self.direction = .vertical
        super.init(frame: frame)
        clipsToBounds = true
        self.addSubview(contentView)
    }
    init(direction: Direction) {
        self.direction = direction
        super.init(frame: CGRect.zero)
        clipsToBounds = true
        translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(contentView)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override func updateConstraints() {
        if !didSetupConstraints {
            contentView.autoPinEdgesToSuperviewEdges()
            switch direction {
            case .vertical:
                contentView.autoMatch(.width, to: .width, of: self)
                contentView.autoSetDimension(ALDimension.height,
                                             toSize: .leastNonzeroMagnitude,
                                             relation: .greaterThanOrEqual)
                break
            case .horizontal:
                contentView.autoMatch(.height, to: .height, of: self)
                contentView.autoSetDimension(ALDimension.width,
                                             toSize: .leastNonzeroMagnitude,
                                             relation: .greaterThanOrEqual)
            }
            didSetupConstraints = true
        }
        super.updateConstraints()
    }
}

这是我的限制条件:

private func configureMainScrollView() {
        scrollView.backgroundColor = .clear
        scrollView.delegate = self
        scrollView.alwaysBounceVertical = true
        scrollView.contentInset = UIEdgeInsets(top: 78, left: 0, bottom: 0, right: 0)
        
        view.addSubview(scrollView)
        
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.topAnchor.constraint(equalTo: customSpacer.bottomAnchor).isActive = true
        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: customAdContainerView.topAnchor).isActive = true
        
        scrollView.contentView.addSubview(customContainerView)
        configureCustomView()
        
        scrollView.contentView.addSubview(collectionView)
        configureCollectionView()
    }
    
    private func configureCustomizeButtonView() {
        customContainerView.backgroundColor = .clear
        
        customButton.setTitle("Customize", for: .normal)
        customButton.backgroundColor = .clear
        customButton.setTitleColor(UIColor.appColorSelectedTab(), for: .normal)
        customButton.titleLabel?.tintColor = UIColor.appColorSelectedTab()
        customButton.titleLabel?.font = UIFont.appFontButtonTitle()
        customButton.contentHorizontalAlignment = .right;
        
        divider.backgroundColor = UIColor.appColorDividerViewBackground()
        
        customContainerView.translatesAutoresizingMaskIntoConstraints = false
        customContainerView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor).isActive = true
        customContainerView.leftAnchor.constraint(equalTo: scrollView.contentView.leftAnchor).isActive = true
        customContainerView.rightAnchor.constraint(equalTo: scrollView.contentView.rightAnchor).isActive = true
        
        customContainerView.addSubview(customButton)
        customContainerView.addSubview(divider)
        
        customButton.translatesAutoresizingMaskIntoConstraints = false
        customButton.topAnchor.constraint(equalTo: customContainerView.topAnchor, constant: 13).isActive = true
        customButton.rightAnchor.constraint(equalTo: customContainerView.rightAnchor, constant: -16).isActive = true
        customButton.leftAnchor.constraint(equalTo: customContainerView.leftAnchor).isActive = true
        customButton.heightAnchor.constraint(equalToConstant: 22).isActive = true
        
        divider.translatesAutoresizingMaskIntoConstraints = false
        divider.topAnchor.constraint(equalTo: customButton.bottomAnchor, constant: 16).isActive = true
        divider.leftAnchor.constraint(equalTo: customContainerView.leftAnchor, constant: 16).isActive = true
        divider.rightAnchor.constraint(equalTo: customContainerView.rightAnchor, constant: -16).isActive = true
        divider.bottomAnchor.constraint(equalTo: customizeButtonContainerView.bottomAnchor).isActive = true
        divider.heightAnchor.constraint(equalToConstant: 1).isActive = true
    }
    
    private func configureCollectionView() {
        collectionView.backgroundColor = .clear
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.isScrollEnabled = false
        
        collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: customCellId)
        collectionView.register(CustomHeaderCollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: customHeaderId)
        
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.topAnchor.constraint(equalTo: customContainerView.bottomAnchor).isActive = true
        collectionView.leftAnchor.constraint(equalTo: scrollView.contentView.leftAnchor).isActive = true
        collectionView.rightAnchor.constraint(equalTo: scrollView.contentView.rightAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: scrollView.contentView.bottomAnchor).isActive = true
        //collectionView.heightAnchor.constraint(equalToConstant: 750).isActive = true
    }

我想知道是不是 UIScrollView 中的 'contentView' 以某种方式导致了这种情况。您会注意到为 collectionView 设置高度约束的注释掉的代码。这是它显示的唯一方式,但显然我正在寻找它来显示 collectionView 的 contentView 大小。

如有任何帮助,我们将不胜感激。谢谢!

UICollectionView需要高度限制(与任何UIScrollView一样)。

不要混淆 frame.heightcontentSize.height

假设一个 UIScrollView 的高度为 200,内容高度为 1000。它知道它需要滚动以显示 200 高度内的所有内容。

如果您不将 frame.height 设置为 200,无论 contentSize.height 是什么 - 它都不会显示任何内容。

本案亦同。 UICollectionView 需要高度限制,即使您不希望它滚动。

这里你要的是frame.height == contentSize.height.

尝试以下操作:

  1. 像这样在 class 中声明一个变量。
private var contentSizeObservation: NSKeyValueObservation?
  1. 给collectionView添加高度约束,开始观察contentSize的变化。
let cvHeight = collectionView.heightAnchor.constraint(equalToConstant: 0)
cvHeight.isActive = true

contentSizeObservation = collectionView.observe(\.contentSize, options: .new, changeHandler: { (cv, _) in
    cvHeight.constant = cv.collectionViewLayout.collectionViewContentSize.height
})
  1. 不要忘记在 deinit 调用 -
  2. 中清理它
deinit {
    contentSizeObservation?.invalidate()
}

这种方法将确保您的 collectionView 的高度始终与其内容一样大。