CGRect 与程序化 GUI 设计中的约束?

CGRect vs constraints in programmatic GUI Design?

我们在框架内使用 CGRect 指定矩形(形状)的宽度、高度和精确坐标。

我是否也需要为 UI 个元素一一指定约束条件?如果是,我为什么需要这样做?设备旋转(纵向与横向模式)如何?我需要定义不同的定位吗?

如果您要定义约束,则不必为您的设计指定 CGRect 框架。事实上最好的方法是使用 NSLayoutConstraints。原因是如果您设置了 CGRect 框架,当您的设备大部分时间都在旋转时,您的 CGRect 可能是错误的。至少高和。但是如果你在设备旋转时使用约束,它会自动重新布局子视图。这意味着视图将根据约束重新排列。

当您设置 CGRect 框架时,它会改变视图的位置和尺寸,而不管约束如何。然后,如果您尝试调用 view.layoutIfNeeded() 或更改方向,则无论您之前设置的框架如何,视图都将根据约束重新排列。

tl;博士

约束是描述视图大小的一种丰富的描述性方式。手动设置框架(和自动调整掩码)是一种古老得多的模式,既不灵活也不强大。你当然可以设置frameautoresizingMask,但我们通常不这样做,现在我们倾向于使用约束。


定义视图的框架时,您有两种选择:


例如,如果你想定义一个图像视图水平插入 50pt,垂直插入 100pt,你可以这样做:

  • 使用约束:

     imageView.translatesAutoresizingMaskIntoConstraints = false
     NSLayoutConstraint.activate([
         imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
         imageView.trailingAnchor.constraint(equalTo: view.leadingAnchor, constant: -50),
         imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
         imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -100)
     ])
    
  • 使用frame/autoresizing掩码:

     imageView.translatesAutoresizingMaskIntoConstraints = true
     imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
     imageView.frame = view.bounds.insetBy(dx: 50, dy: 100)
    

有几点需要注意:

  • 手动设置 frame 意味着您无法响应旋转(或其他可能改变父视图大小的事件)的结论是不正确的。 autoresizingMask 可以非常优雅地处理大多数基本的调整大小逻辑。 (坦率地说,这就是我们在引入 auto-layout 引擎之前所做的。)

  • 从技术上讲,这两种方法实际上都是在幕后使用约束。 autoresizingMask/frametranslatesAutoresizingMaskIntoConstraints 只是将 frameautoresizingMask 转换为约束。

  • auto-layout 引擎和约束是一个更加丰富的范例:

    • 您可以轻松定义视图层次结构不同级别视图之间的约束and/or布局指南之间。
    • 它们支持更复杂的规则,包括单独的乘数和常量参数、不等运算符、级联优先级等。
    • 它们支持 right-to-left 种语言的动态布局。
    • 它们支持针对不同大小特征的不同布局(例如,根据视图的相对宽度或高度动态重新排列项目)。

    所有这些功能在很大程度上消除了编写响应子视图布局的代码的需要。

简而言之,使用约束在很大程度上取代了设置 frameautoresizingMask 的旧技术。