【问题标题】:UIScrollView Not Recognizing UICollectionView's Content SizeUIScrollView 无法识别 UICollectionView 的内容大小
【发布时间】:2021-03-29 15:16:43
【问题描述】:

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

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

这是自定义的 UIScrollView 类:

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 大小。

对此的任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 你所说的customContainerView和collectionView的东西是从哪里来的?
  • 你自己在什么类下编写 configureMainScrollView 和其他函数可能很明显。对你来说显而易见的事情对其他人来说并不明显。
  • 配置方法在我的视图控制器中。我在视图控制器的顶部声明这些 UI 元素,并在 ViewDidLoad 中调用的这些方法中设置约束。 @ElTomato

标签: ios swift uicollectionview uiscrollview swift4


【解决方案1】:

UICollectionView 需要高度限制(与任何UIScrollView 相同)。

不要混淆frame.heightcontentSize.height

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

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

这同样适用于这种情况。 UICollectionView 需要高度限制,即使您不希望它滚动。

你想要的是frame.height == contentSize.height

尝试以下:

  1. 像这样在类中声明一个变量。
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 电话中清理它 -
deinit {
    contentSizeObservation?.invalidate()
}

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

【讨论】:

  • 这成功了!感谢您的解释帮助我理解问题,而不仅仅是提供答案。非常感激。 @Tarun
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
相关资源
最近更新 更多