如何设置 NSLayoutAnchor 以生成具有宽高比 1:1 的居中子视图

How to set the NSLayoutAnchor to generate an centered subview with aspect ratio 1:1

听起来并不太难,但经过几个小时的尝试我无法找到合适的解决方案。

问题:我想设置约束(使用 class NSLayoutAnchor)来让子视图(colorImageView)在父视图中 centered 纵横比 1:1 并且总是在 最大尺寸 可能在超级视图中有时宽度 > 高度或高度 > 宽度。

示例 1: SuperViewSize = width : 80, height = 100 -> 子视图的高度和宽度应为 80 且居中于 (40/50)

示例 2: SuperviewSize = width : 60, height = 50 -> 子视图的高度和宽度应为 50 且居中于 (30/25)

我不想/它不能解决问题/硬编码一个 widthConstraint = min(superviewWidth, superviewHeight) 因为在创建子视图的那一刻,superviews 边界没有最终定义 -> 所以我需要一个约束。

这是我到目前为止的尝试(仍然缺少在不同的超级视图中将高度和宽度设置为最大可能的限制:

// CREATE CONSTRAINTS(center in SuperView)
colorImageView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
colorImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true

// CREATE CONSTRAINTS (ratio 1:1)
colorImageView.widthAnchor.constraint(equalTo: colorImageView.heightAnchor, multiplier: 1.0).isActive = true

我真的很感激提示,如何做到这一点。提前致谢:))

完成这项工作的关键是将 colorImageView 的宽度设置为其父视图的宽度,但优先级为 750(而不是默认的 1000)。

然后将 colorImageView 的高度设置为 lessThanOrEqualTo 其父视图的高度。

Auto Layout 将尽力满足这两个新约束。

当视图的宽度大于它的高度时,它将无法使 colorImageView 的宽度等于视图的宽度,但这没关系,因为优先级为 750。它将使它在不违反其他完整优先级约束的情况下尽可能大。

当视图的高度大于其宽度时,它将能够满足所有约束,因为 colorView 的高度是 lessThanOrEqualTo 视图的高度。

import UIKit

let view = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 100))
view.backgroundColor = .red

let colorImageView = UIView()
colorImageView.translatesAutoresizingMaskIntoConstraints = false
colorImageView.backgroundColor = .yellow

view.addSubview(colorImageView)

// CREATE CONSTRAINTS(center in SuperView)
colorImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
colorImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

// CREATE CONSTRAINTS (ratio 1:1)
colorImageView.widthAnchor.constraint(equalTo: colorImageView.heightAnchor, multiplier: 1.0).isActive = true

let widthConstraint = colorImageView.widthAnchor.constraint(equalTo: view.widthAnchor)
widthConstraint.priority = UILayoutPriority(rawValue: 750)
widthConstraint.isActive = true

colorImageView.heightAnchor.constraint(lessThanOrEqualTo: view.heightAnchor).isActive = true

view.layoutIfNeeded()

view.frame = CGRect(x: 0, y: 0, width: 60, height: 50)
view.layoutIfNeeded()

这里是 运行 游乐场: