【问题标题】:Swift UIView's sizeToFit() always returning 0 in heightSwift UIView 的 sizeToFit() 总是返回 0 的高度
【发布时间】:2020-04-22 07:18:36
【问题描述】:

我正在尝试创建一个 ViewBuilder 类来设置视图并将它们返回给调用者。然后,调用者只需约束一个视图,该视图包含一些在视图内受约束的子视图。这样,我想保存一些代码。

代码会变得更清楚:

我的 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 类中的代码:

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 没有包含其子视图(在这种情况下,它是一个包含帖子描述的标签;您看到的边框不是来自 postView,而是来自正确调整大小的标签它的高度根据内容)。这种行为会导致整个视图变砖。

我真的不知道问题出在哪里,非常感谢您提供一些建议。提前致谢!

【问题讨论】:

  • 你在DefaultLabel中实现了sizeThatFits:吗?
  • 没有。但是标签本身具有正确的 sizeToFit 行为?
  • 我建议不要使用sizeToFit。大约 6 年前,当我们从自动调整大小切换到自动布局时,这是一种旧方法,大部分已被其他方法取代。
  • 感谢您的评论。还有哪些其他方法?
  • @linus_hologram intrinsicContentSize 并正确设置拥抱和压缩阻力。由于其固有尺寸,您的标签已经具有正确的尺寸,您只需为postView 提供正确的约束。而且您已经找到了正确的解决方案:)

标签: ios swift uiview nslayoutconstraint ios-autolayout


【解决方案1】:

我找到了答案:只需将postView 的bottomAnchor 约束到标签bottomAnchor,如下所示:

postView.bottomAnchor.constraint(equalTo: postDescription.bottomAnchor).isActive = true

这就是所有的魔法。一切看起来都应该:)

【讨论】:

    【解决方案2】:

    您的视图大小不正确,因为您返回的视图只是一个普通的UIView 实例,其中包含一个子视图。 UIView 的默认 sizeThatFits(_:) 实现将返回 CGSize.zero

    你有几个选择:

    1. 创建一个子类UIViewPostView 类。您应该将DefaultLabel 实例作为子视图添加到此视图,类似于您在generatePostView(postItem:) -> UIView 中执行此操作的方式。然后,您应该在PostView 中实现sizeThatFits(_:),它使用DefaultLabelsizeThatFits(_:) 值来计算要返回的正确大小。
    2. 在您的generatePostView(postItem:) -> UIView 方法中,只需返回postDescription 实例,而不是将其添加到另一个UIView 实例。我将此列为您的第二个选项,因为我猜您计划在容器视图中添加更多的子视图,而不仅仅是 postDescription,因此选项 1 将来更容易添加更多子视图。

    【讨论】:

    • 感谢您的回答。您介意提供一个代码示例吗?
    • 嘿,你介意在聊天中继续讨论吗? chat.stackoverflow.com/rooms/205355/…
    • 没关系,我找到了解决方案。我只是将 postViews 底部 Anchor 限制为标签底部 Anchor。
    【解决方案3】:

    正如layoutSubviews 的文档中所述,永远不应直接调用它。修改为正确的

    /* postView.layoutSubviews() */
    
      postView.setNeedsLayout()
      postView.layoutIfNeeded()
    

    【讨论】:

    • 不幸的是,这仍然不能解决问题。你还有什么想法吗?
    • 简单的方法是使用stackView而不是UIView()
    • 这并不能解决这个问题。它变砖了,因为它不知道它的子视图有哪个高度......在这种情况下,Stack View 将如何帮助?我仍然必须执行某种 sizeToFit 以使 StackView 适合所有子视图,对吧?
    • 不...没有必要在stackview上调用sizetofit
    • 是的,它会自动排列它的子视图,但我希望子视图有自己的大小和相应的堆栈视图大小
    猜你喜欢
    • 2016-05-16
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 2014-03-20
    • 2013-04-13
    相关资源
    最近更新 更多