【问题标题】:Subview autolayout constraints in init初始化中的子视图自动布局约束
【发布时间】:2023-03-31 06:44:01
【问题描述】:

我有一个自定义 UIView,它是 UIScrollView 的子类。在 init(_ frame) 方法中,我添加了一个子视图,如下所示:

    contentView = ContentView()
    contentView.backgroundColor = UIColor.blue
    contentView.translatesAutoresizingMaskIntoConstraints = false

    self.addSubview(contentView)

    contentView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    contentView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
    contentView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    
    // create contentView's Width and Height constraints
    cvWidthConstraint = contentView.widthAnchor.constraint(equalToConstant: 0.0)
    cvHeightConstraint = contentView.heightAnchor.constraint(equalToConstant: 0.0)
           
    // activate them
    cvWidthConstraint.isActive = true
    cvHeightConstraint.isActive = true

    cvWidthConstraint.constant = timelineWidth //It's non-zero
    cvHeightConstraint.constant = 2.0*frame.height

问题是更新 contentView 框架需要时间。它肯定不会在 init(_ frame) 调用中更新。 contentView 框架何时设置以及如何捕获框架更新事件?

【问题讨论】:

  • 首先,您的代码没有显示contentView 被添加为子视图。第二,你是什么意思“更新contentView框架需要时间”?第三,您应该将contentView 限制为滚动视图的contentLayoutGuide。但是,您发布的问题缺少解释正在发生的事情并给您答案所需的信息。
  • 对不起,我错过了发布 addSubview 行,没有它显然代码会崩溃,现在添加它。此初始化发生在 init(_frame) 中。我在同一个调用中需要 contentView.frame ,但在这个调用中它是 CGRect.zero 。在 layoutSubviews 被调用之前它不会被设置。
  • “我在同一个调用中需要 contentView.frame...” -- 为什么?从您发布的代码和您的描述来看,scrollView 中没有任何内容可以滚动。如果您要向contentView 添加子视图,请给它们适当的约束,以便contentView 将保留它们并自动处理可滚动区域。
  • 因为在这个 UIScrollView 之外有一个外部视图,它的帧同步到这个 contentView 帧。每当 contentView 框架发生变化时,都需要重新绘制它。
  • 使用您显示的代码,您已将contentView 宽度和高度约束设置为零。你预计框架什么时候会改变?这个“外部视图”是什么,它被限制在什么范围内?如果您不告诉我们您要做什么,我们无法猜测如何为您提供帮助。

标签: ios swift uiview uiscrollview uikit


【解决方案1】:

在设置约束之前,我会确保将视图添加到父视图,例如“self.addSubview(contentView)”。如果“self”视图已经添加到视图层次结构中,那么 contentView 布局将立即生效。或者,您可以覆盖方法 viewDidMoveToSuperview,然后检查 superview 是否不为零,如果是,则初始化并将子视图 contentView 插入它

【讨论】:

    【解决方案2】:

    里面

    override func layoutSubviews() {
      super.layoutSubviews()
      // to do  
    }
    

    你得到父视图的实际框架,但请记住,因为它被多次调用

    【讨论】:

    • 是的,我通过使用布尔值来测试设置是否第一次完成。因为 layoutSubviews 会被调用很多次。不过,这似乎是一种解决方法,并不理想。
    猜你喜欢
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    相关资源
    最近更新 更多