即使设置了约束,UIView 也会被裁掉

UIView cropped off even though constraints are set

我在 xib 文件中创建了一个自定义视图,我在其中将所有模拟指标设置为 "Inferred"

在我看来,我通过固定左侧和顶部将一个堆栈视图 x 浮动到左侧,通过固定右侧和顶部将堆栈视图浮动到右侧。有点像这样(= 符号表示屏幕边框)

==========
=x      y=
=        =
=        =
=        =
=        = 
==========

我没有对宽度和高度设置任何限制,因为一切都应该是推断出来的。

对应的class我的看法很简单:

class MyView: UIView {

    var view:UIView!
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        view = UIView.loadFromNibNamed("MyView")
        addSubview(view)
    }
}
extension UIView {

    class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> UIView? {
        return UINib(
            nibName: nibNamed,
            bundle: bundle
            ).instantiateWithOwner(nil, options: nil)[0] as? UIView
    }

}

我在情节提要中使用此视图,方法是将它固定在左侧、右侧、顶部和底部。 .

问题是视图是从笔尖加载的,但宽度不是动态的。我希望视图根据父级的大小调整自身大小。但是,即使我设置了约束,右侧堆栈视图的大约 1/3 被裁掉并且在屏幕上不可见。

我该怎么做才能解决这个问题?

  1. 我们需要确定问题所在,所以让我们首先确认堆栈视图正在获取其框架集。在堆栈视图所在的视图控制器中,我们可以覆盖 following methods 并检查堆栈视图的框架。

      viewWillLayoyutSubviews()
      viewDidLayoutSubviews()
    
  2. 确认框架已设置,我们现在可以查看在故事板中设置的约束。您提供的信息并不清晰,您希望如何将堆栈视图布局在一起,一个在另一个视图之上?他们应该是 side-by-side 吗?

    您需要检查约束是否对您想要的布局有效。

3.Confirm 您的视图的大小 类 配置正确。 Apple 在此处有一个名为“Size Classes Design Help”的文档。我相信这是你的问题。您的自定义 class 设置为具有 Any/Any 的大小 class 并且自定义视图的超级视图具有一组不同的大小 classes,例如 Compact/Regular.因此,您的自定义视图 而不是 根据大小 classes 调整其大小,因为它对于任何大小 classes 的组合都设置为相同。尝试为您的自定义 class 配置不同的大小 class 组合,以查看是否存在任何差异 - 例如 Compact/Regular。

如果您希望从 XIB 加载的任何视图具有动态帧大小,则需要将 translatesAutoresizingMaskIntoConstraints 属性 设置为 false。否则系统会自动创建布局约束,例如固定宽度和固定高度,以防止您的视图调整大小。

此外,在将视图添加到视图层次结构后,您需要在代码中添加一些约束,将其顶部、底部、左侧和右侧边缘固定到其父视图的相应边缘。毕竟,您将 XIB 的内容作为子视图添加到您的自定义视图 MyView 即这两个视图不相同,您需要告诉系统它应该如何定位子视图(您添加的约束故事板仅与您的 MyView 实例相关,与其子视图无关)。添加到您的代码中应该可以解决问题:

class MyView: UIView {

    var view:UIView!
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        view = UIView.loadFromNibNamed("MyView")
        view.translatesAutoresizingMaskIntoConstraints = false
        addSubview(view)

        // Pin view to all four edges of its superview
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: [], metrics: nil, views: ["view": view]))
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: [], metrics: nil, views: ["view": view]))

    }
}

旁注:

  • 阅读 official documentation 中关于 translatesAutoresizingMaskIntoConstraints 属性 的更详细解释。
  • Interface Builder "simulated metrics" 部分中的所有设置仅适用于 Interface Builder 本身。当您在模拟器或真实设备上 运行 应用时,它们不会对您的应用产生任何影响。