简体   繁体   English

内置UIImageView的UIStackView上的自动布局 - iOS Swift

[英]Auto Layout on UIStackView with UIImageView inside - iOS Swift

I have some issues with auto layout when building view programmatically. 在以编程方式构建视图时,我遇到了一些自动布局问题。

There is a vertical UIStackView with several elements inside, mainly labels and images. 有一个垂直的UIStackView,里面有几个元素,主要是标签和图像。 After setting properties on stackView and imageView, as a result I get something similar to image 1 below (white spaces on top and bottom of the image; the smaller screen size the bigger white spaces) while I would like to get something more similar to image 2 (without white spaces around image). 在stackView和imageView上设置属性之后,我得到了类似于下面图像1的东西(图像顶部和底部的空白区域;屏幕尺寸越小,白色空间越大),而我希望得到更类似于图像的东西2(图像周围没有空白区域)。

1: 1:

图像周围的空白区域

2: 2:

图像周围没有空白区域

I was reading some tutorials on how to properly set the stackView, its distribution and alignment and as a result in my StackView properties are set like this: 我正在阅读一些关于如何正确设置stackView,它的分布和对齐的教程,因此我的StackView属性设置如下:

myStackView.axis = .vertical
myStackView.distribution = .fill
myStackView.alignment = .fill
myStackView.spacing = 12
myStackView.contentMode = .scaleAspectFit

and on ImageView before I add it as an arranged subview, I set: 在我将它添加为排列的子视图之前在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)

I did not change CHP and CCRP on labels above and under the imageView. 我没有在imageView上方和下方的标签上更改CHP和CCRP。

I was trying to manipulate with content hugging priority and content compressions resistance priority but it did not change anything. 我试图操纵内容拥抱优先级和内容压缩阻力优先但它没有改变任何东西。 Any ideas what I do wrong? 我有什么想法吗?

I suspect the problem here as is that the hugging and compression-resistance priorities apply to the view's intrinsic content size, and the intrinsic content size of a UIImageView is the natural size of the image. 我怀疑这里的问题是,拥抱和压缩阻力优先级适用于视图的内在内容大小,而UIImageView的内在内容大小是图像的自然大小。 But you want the image to be scaled to fit the width of the screen, which means that (in general) you don't want the image view's size to be the natural size of its image. 但是您希望缩放图像以适应屏幕的宽度,这意味着(通常)您不希望图像视图的大小为其图像的自然大小。 Thus the hugging and compression-resistance priorities will not help you. 因此,拥抱和抗压力优先级对您没有帮助。

What you need to do is add two constraints: 您需要做的是添加两个约束:

  • Constrain the image view's width to equal the stack view's width. 将图像视图的宽度限制为等于堆栈视图的宽度。 You can do this in the storyboard or in code. 您可以在故事板或代码中执行此操作。 In code: 在代码中:

     myImageView.widthAnchor.constraint(equalTo: myStackView.widthAnchor).isActive = true 
  • Constrain the image view's aspect ratio to match the image's aspect ratio. 约束图像视图的纵横比以匹配图像的纵横比。 If you change the image at runtime, you need to do this in code, like this: 如果在运行时更改图像,则需要在代码中执行此操作,如下所示:

     // 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 

These two required constraints will force the image view to be exactly the right height to perfectly contain the scaled image. 这两个必需的约束将强制图像视图完全正确的高度,以完美地包含缩放图像。

You may still run into trouble if you have constrained the height of the stack view to match the height of some other view—for example, your top-level view. 如果限制堆栈视图的高度以匹配其他视图的高度(例如,顶级视图),则可能仍会遇到麻烦。 (If your stack view is your top-level view, it is effectively constrained to fill the screen.) In that case, the stack view will stretch or shrink at least one of its arranged subviews as needed to fill that height. (如果您的堆栈视图您的顶级视图,则它实际上被约束为填充屏幕。)在这种情况下,堆栈视图将根据需要拉伸或缩小其排列的子视图中的至少一个以填充该高度。

If none of the arranged subviews has a flexible height, then auto layout may end up breaking the image view's aspect ratio constraint so it can stretch the image view to fill the needed space. 如果排列的子视图都没有灵活的高度,那么自动布局可能会最终破坏图像视图的宽高比约束,因此它可以拉伸图像视图以填充所需的空间。 Or it may stretch some other view that you don't want stretched. 或者它可能会延伸一些您不想拉伸的视图。

If that's happening, you have three options: 如果发生这种情况,您有三种选择:

  • Remove the constraint that's forcing the stack view to fill the height of some other view. 删除强制堆栈视图填充其他视图高度的约束。 Then auto layout will set the height of the stack view to exactly contain its arranged subviews at their preferred sizes (based on constraints or intrinsic content size). 然后,自动布局将设置堆栈视图的高度,以精确包含其首选大小的排列子视图(基于约束或内在内容大小)。

  • Lower the vertical hugging and/or compression resistance priority of one or more arranged subviews that you want resized to fill the required height. 降低要调整大小以填充所需高度的一个或多个已排列子视图的垂直拥抱和/或压缩阻力优先级。

  • Add a “padding” UIView to the stack view to absorb the additional height. 在堆栈视图中添加“填充” UIView以吸收额外的高度。 Set its background color to nil or .clear so it's not visible. 将其背景颜色设置为nil或.clear ,使其不可见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM