Swift UIView 的 sizeToFit() 总是返回 0 的高度
Swift UIView's sizeToFit() always returning 0 in height
我正在尝试创建一个 ViewBuilder class 来设置视图并将它们 returns 给调用者。然后调用者只需要约束一个视图,该视图包含一些在视图内受约束的子视图。这样,我想节省一些代码。
代码会让事情变得更清楚:
我的 Collection-View-Cell 中的代码:
let postView = ViewComponentsBuilder.generatePostView(postItem: contentInteraction!.nativeContent as! Post)
postView.layer.borderWidth = 1
self.contentView.addSubview(postView)
postView.anchor(top: profileImageView.bottomAnchor, left: self.contentView.leftAnchor, bottom: nil, right: self.contentView.rightAnchor, paddingTop: 0, paddingLeft: 16, paddingBottom: 0, paddingRight: 16, width: 0, height: 0)
postView.layoutSubviews()
postView.sizeToFit()
print(postView.frame.height) // always prints 0
ViewBuilder 中的代码Class:
static func generatePostView(postItem: Post) -> UIView {
let postDescription: DefaultLabel = {
let lbl = DefaultLabel(labelFont: UIFont(name: "Montserrat-Medium", size: 16)!, labelTextColor: .black, labelText: "")
lbl.numberOfLines = 0
lbl.text = postItem.content.message
lbl.layer.borderWidth = 1
return lbl
}()
let postView = UIView()
postView.addSubview(postDescription)
postDescription.anchor(top: postView.topAnchor, left: postView.leftAnchor, bottom: nil, right: postView.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
postDescription.sizeToFit()
postView.layoutSubviews()
return postView
}
这是我得到的行为:
如您所见,从 ViewComponentsBuilder 生成的 postView 没有包含其子视图(在本例中它是一个包含 post 描述的标签;边框您看到的不是来自 post 视图,而是来自根据内容 正确调整高度的标签。此行为导致整个视图变砖。
我真的不知道问题出在哪里,非常感谢您提供一些建议。提前致谢!
如 layoutSubviews
的文档中所述,永远不应直接调用它。修改为正确的
/* postView.layoutSubviews() */
postView.setNeedsLayout()
postView.layoutIfNeeded()
您的视图未正确调整大小,因为您 return 的视图只是一个普通的 UIView
实例,其中有一个子视图。 UIView
的默认 sizeThatFits(_:)
实现只是 return CGSize.zero
.
这里有几个选项:
- 创建一个
PostView
class 子 class 是 UIView
。您应该添加一个 DefaultLabel
实例作为该视图的子视图,类似于您在 generatePostView(postItem:) -> UIView
中的做法。然后,您应该在 PostView
中实现 sizeThatFits(_:)
,它使用 DefaultLabel
的 sizeThatFits(_:)
值来计算 return. 的正确大小
- 在您的
generatePostView(postItem:) -> UIView
方法中,只需 return postDescription
实例,而不是将其添加到另一个 UIView
实例。我将此列为您的第二个选项,因为我猜您计划向容器视图添加更多子视图,而不仅仅是 postDescription
,因此选项 1 将来更容易添加更多子视图。
我找到了答案:只需将 postView
的 bottomAnchor 约束到标签 bottomAnchor,如下所示:
postView.bottomAnchor.constraint(equalTo: postDescription.bottomAnchor).isActive = true
这就是所有的魔法。一切看起来都应该如此:)
我正在尝试创建一个 ViewBuilder class 来设置视图并将它们 returns 给调用者。然后调用者只需要约束一个视图,该视图包含一些在视图内受约束的子视图。这样,我想节省一些代码。
代码会让事情变得更清楚:
我的 Collection-View-Cell 中的代码:
let postView = ViewComponentsBuilder.generatePostView(postItem: contentInteraction!.nativeContent as! Post)
postView.layer.borderWidth = 1
self.contentView.addSubview(postView)
postView.anchor(top: profileImageView.bottomAnchor, left: self.contentView.leftAnchor, bottom: nil, right: self.contentView.rightAnchor, paddingTop: 0, paddingLeft: 16, paddingBottom: 0, paddingRight: 16, width: 0, height: 0)
postView.layoutSubviews()
postView.sizeToFit()
print(postView.frame.height) // always prints 0
ViewBuilder 中的代码Class:
static func generatePostView(postItem: Post) -> UIView {
let postDescription: DefaultLabel = {
let lbl = DefaultLabel(labelFont: UIFont(name: "Montserrat-Medium", size: 16)!, labelTextColor: .black, labelText: "")
lbl.numberOfLines = 0
lbl.text = postItem.content.message
lbl.layer.borderWidth = 1
return lbl
}()
let postView = UIView()
postView.addSubview(postDescription)
postDescription.anchor(top: postView.topAnchor, left: postView.leftAnchor, bottom: nil, right: postView.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
postDescription.sizeToFit()
postView.layoutSubviews()
return postView
}
这是我得到的行为:
如您所见,从 ViewComponentsBuilder 生成的 postView 没有包含其子视图(在本例中它是一个包含 post 描述的标签;边框您看到的不是来自 post 视图,而是来自根据内容 正确调整高度的标签。此行为导致整个视图变砖。
我真的不知道问题出在哪里,非常感谢您提供一些建议。提前致谢!
如 layoutSubviews
的文档中所述,永远不应直接调用它。修改为正确的
/* postView.layoutSubviews() */
postView.setNeedsLayout()
postView.layoutIfNeeded()
您的视图未正确调整大小,因为您 return 的视图只是一个普通的 UIView
实例,其中有一个子视图。 UIView
的默认 sizeThatFits(_:)
实现只是 return CGSize.zero
.
这里有几个选项:
- 创建一个
PostView
class 子 class 是UIView
。您应该添加一个DefaultLabel
实例作为该视图的子视图,类似于您在generatePostView(postItem:) -> UIView
中的做法。然后,您应该在PostView
中实现sizeThatFits(_:)
,它使用DefaultLabel
的sizeThatFits(_:)
值来计算 return. 的正确大小
- 在您的
generatePostView(postItem:) -> UIView
方法中,只需 returnpostDescription
实例,而不是将其添加到另一个UIView
实例。我将此列为您的第二个选项,因为我猜您计划向容器视图添加更多子视图,而不仅仅是postDescription
,因此选项 1 将来更容易添加更多子视图。
我找到了答案:只需将 postView
的 bottomAnchor 约束到标签 bottomAnchor,如下所示:
postView.bottomAnchor.constraint(equalTo: postDescription.bottomAnchor).isActive = true
这就是所有的魔法。一切看起来都应该如此:)