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.height
和 contentSize.height
。
假设一个 UIScrollView
的高度为 200,内容高度为 1000。它知道它需要滚动以显示 200 高度内的所有内容。
如果您不将 frame.height
设置为 200,无论 contentSize.height
是什么 - 它都不会显示任何内容。
本案亦同。 UICollectionView
需要高度限制,即使您不希望它滚动。
这里你要的是frame.height == contentSize.height
.
尝试以下操作:
- 像这样在 class 中声明一个变量。
private var contentSizeObservation: NSKeyValueObservation?
- 给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
})
- 不要忘记在
deinit
调用 - 中清理它
deinit {
contentSizeObservation?.invalidate()
}
这种方法将确保您的 collectionView 的高度始终与其内容一样大。
我有这个自定义的 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.height
和 contentSize.height
。
假设一个 UIScrollView
的高度为 200,内容高度为 1000。它知道它需要滚动以显示 200 高度内的所有内容。
如果您不将 frame.height
设置为 200,无论 contentSize.height
是什么 - 它都不会显示任何内容。
本案亦同。 UICollectionView
需要高度限制,即使您不希望它滚动。
这里你要的是frame.height == contentSize.height
.
尝试以下操作:
- 像这样在 class 中声明一个变量。
private var contentSizeObservation: NSKeyValueObservation?
- 给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
})
- 不要忘记在
deinit
调用 - 中清理它
deinit {
contentSizeObservation?.invalidate()
}
这种方法将确保您的 collectionView 的高度始终与其内容一样大。