在 UIStackView 上使用 UIImageView 自动布局 - iOS Swift
Auto Layout on UIStackView with UIImageView inside - iOS Swift
我在以编程方式构建视图时遇到一些自动布局问题。
有一个垂直的UIStackView,里面有几个元素,主要是标签和图片。在 stackView 和 imageView 上设置属性后,结果我得到类似于下面的图像 1 的东西(图像顶部和底部的空白;屏幕尺寸越小,空白越大),而我想得到更类似于图像的东西2(图片周围没有空白)。
1:
2:
我正在阅读一些关于如何正确设置 stackView、其分布和对齐方式的教程,因此我的 StackView 属性设置如下:
myStackView.axis = .vertical
myStackView.distribution = .fill
myStackView.alignment = .fill
myStackView.spacing = 12
myStackView.contentMode = .scaleAspectFit
在将 ImageView 添加为已排列的子视图之前,我设置了:
myImageView.contentMode = .scaleAspectFit
myImageView.autoresizesSubviews = true
myImageView.sd_setImage(with: URL(string: image))
myImageView.setContentHuggingPriority(251, for: .horizontal)
myImageView.setContentHuggingPriority(500, for: .vertical)
myImageView.setContentCompressionResistancePriority(750, for: .horizontal)
myImageView.setContentCompressionResistancePriority(750, for: .vertical)
我没有更改 imageView 上方和下方标签上的 CHP 和 CCRP。
我试图用内容拥抱优先级和内容压缩阻力优先级进行操作,但它没有改变任何东西。知道我做错了什么吗?
我怀疑这里的问题是拥抱和抗压缩优先级适用于视图的固有内容大小,而 UIImageView
的固有内容大小是图像的自然大小。但是您希望缩放图像以适合屏幕宽度,这意味着(通常)您不希望图像视图的大小是其图像的自然大小。因此拥抱和抗压优先级对你没有帮助。
你需要做的是添加两个约束:
将图像视图的宽度限制为等于堆栈视图的宽度。您可以在故事板或代码中执行此操作。在代码中:
myImageView.widthAnchor.constraint(equalTo: myStackView.widthAnchor).isActive = true
限制图像视图的纵横比以匹配图像的纵横比。如果在 运行 时更改图像,则需要在代码中执行此操作,如下所示:
// Instance variable:
var imageAspectRatioConstraint: NSLayoutConstraint?
// When you set the image:
imageAspectRatioConstraint?.isActive = false
imageAspectRatioConstraint = myImageView.widthAnchor.constraint(
equalTo: myImageView.heightAnchor,
multiplier: myImageView.image!.size.width / myImageView.image!.size.height)
imageAspectRatioConstraint!.isActive = true
这两个必需的约束将强制图像视图的高度恰好正确,以完美包含缩放后的图像。
如果您已将堆栈视图的高度限制为与某些其他视图(例如,您的顶级视图)的高度相匹配,您可能仍然 运行 会遇到麻烦。 (如果您的堆栈视图 是 您的顶级视图,它实际上被限制为充满屏幕。)在这种情况下,堆栈视图将至少拉伸或收缩其排列的子视图之一根据需要填充该高度。
如果排列的 none 个子视图具有灵活的高度,那么自动布局最终可能会打破图像视图的纵横比约束,因此它可以拉伸图像视图以填充所需的 space。或者它可能会拉伸一些您不想拉伸的其他视图。
如果发生这种情况,您有以下三种选择:
删除强制堆栈视图填充其他视图高度的约束。然后自动布局将设置堆栈视图的高度以准确包含其首选大小的排列子视图(基于约束或内在内容大小)。
降低一个或多个要调整大小以填充所需高度的子视图的垂直拥抱 and/or 压缩阻力优先级。
向堆栈视图添加“填充”UIView
以吸收额外的高度。将其背景颜色设置为 nil 或 .clear
使其不可见。
我在以编程方式构建视图时遇到一些自动布局问题。
有一个垂直的UIStackView,里面有几个元素,主要是标签和图片。在 stackView 和 imageView 上设置属性后,结果我得到类似于下面的图像 1 的东西(图像顶部和底部的空白;屏幕尺寸越小,空白越大),而我想得到更类似于图像的东西2(图片周围没有空白)。
1:
2:
我正在阅读一些关于如何正确设置 stackView、其分布和对齐方式的教程,因此我的 StackView 属性设置如下:
myStackView.axis = .vertical
myStackView.distribution = .fill
myStackView.alignment = .fill
myStackView.spacing = 12
myStackView.contentMode = .scaleAspectFit
在将 ImageView 添加为已排列的子视图之前,我设置了:
myImageView.contentMode = .scaleAspectFit
myImageView.autoresizesSubviews = true
myImageView.sd_setImage(with: URL(string: image))
myImageView.setContentHuggingPriority(251, for: .horizontal)
myImageView.setContentHuggingPriority(500, for: .vertical)
myImageView.setContentCompressionResistancePriority(750, for: .horizontal)
myImageView.setContentCompressionResistancePriority(750, for: .vertical)
我没有更改 imageView 上方和下方标签上的 CHP 和 CCRP。
我试图用内容拥抱优先级和内容压缩阻力优先级进行操作,但它没有改变任何东西。知道我做错了什么吗?
我怀疑这里的问题是拥抱和抗压缩优先级适用于视图的固有内容大小,而 UIImageView
的固有内容大小是图像的自然大小。但是您希望缩放图像以适合屏幕宽度,这意味着(通常)您不希望图像视图的大小是其图像的自然大小。因此拥抱和抗压优先级对你没有帮助。
你需要做的是添加两个约束:
将图像视图的宽度限制为等于堆栈视图的宽度。您可以在故事板或代码中执行此操作。在代码中:
myImageView.widthAnchor.constraint(equalTo: myStackView.widthAnchor).isActive = true
限制图像视图的纵横比以匹配图像的纵横比。如果在 运行 时更改图像,则需要在代码中执行此操作,如下所示:
// Instance variable: var imageAspectRatioConstraint: NSLayoutConstraint? // When you set the image: imageAspectRatioConstraint?.isActive = false imageAspectRatioConstraint = myImageView.widthAnchor.constraint( equalTo: myImageView.heightAnchor, multiplier: myImageView.image!.size.width / myImageView.image!.size.height) imageAspectRatioConstraint!.isActive = true
这两个必需的约束将强制图像视图的高度恰好正确,以完美包含缩放后的图像。
如果您已将堆栈视图的高度限制为与某些其他视图(例如,您的顶级视图)的高度相匹配,您可能仍然 运行 会遇到麻烦。 (如果您的堆栈视图 是 您的顶级视图,它实际上被限制为充满屏幕。)在这种情况下,堆栈视图将至少拉伸或收缩其排列的子视图之一根据需要填充该高度。
如果排列的 none 个子视图具有灵活的高度,那么自动布局最终可能会打破图像视图的纵横比约束,因此它可以拉伸图像视图以填充所需的 space。或者它可能会拉伸一些您不想拉伸的其他视图。
如果发生这种情况,您有以下三种选择:
删除强制堆栈视图填充其他视图高度的约束。然后自动布局将设置堆栈视图的高度以准确包含其首选大小的排列子视图(基于约束或内在内容大小)。
降低一个或多个要调整大小以填充所需高度的子视图的垂直拥抱 and/or 压缩阻力优先级。
向堆栈视图添加“填充”
UIView
以吸收额外的高度。将其背景颜色设置为 nil 或.clear
使其不可见。