简体   繁体   English

了解 Swift 中的布局锚点

[英]Understanding layout anchors in Swift

So, I have this ViewController where I render an image inside a subview.所以,我有这个ViewController ,我在子视图中渲染图像。

class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .systemBackground
    
    let childView = UIView()
    childView.backgroundColor = .red
    
    let imageView = UIImageView(image: UIImage(systemName: "tray"))
    imageView.contentMode = .scaleAspectFill
    
    childView.addSubview(imageView)
    
    imageView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      imageView.heightAnchor.constraint(equalToConstant: 100.0)
    ])
    
    view.addSubview(childView)
    
    childView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      childView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor)
    ])
  }
}

As you can see for some reason, the image moves to the left of screen.如您所见,由于某种原因,图像移动到屏幕左侧。 What is the cause of that?这是什么原因?

在此处输入图像描述

One more thing I noticed is the subview should have a background color of red as specified, but somehow it's transparent.我注意到的另一件事是子视图应该具有指定的红色背景颜色,但不知何故它是透明的。 Why is that?这是为什么?

I expect the result to be something like,我希望结果是这样的,

在此处输入图像描述

You are adding way too few constraints.您添加的约束太少了。 The horizontal position and size of the childView are not constrained at all, so the size just defaults to (0, 0), making the view not visible at all, which is why you don't see the red background.水平 position 和childView的大小完全不受限制,因此大小只是默认为 (0, 0),使视图根本不可见,这就是为什么您看不到红色背景的原因。

First, let's constrain the horizontal position.首先,让我们约束水平 position。 This seems to be what you intended:这似乎是您的意图:

NSLayoutConstraint.activate([
    // wouldn't it be better to use safeAreaLayoutGuide?
    childView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
    childView.leftAnchor.constraint(equalTo: view.layoutMarginsGuide.leftAnchor)
])

Then, the size of the childView should be the same as the imageView , so you should activate these constraints too:然后, childView的大小应该与imageView相同,因此您也应该激活这些约束:

imageView.leftAnchor.constraint(equalTo: childView.leftAnchor),
imageView.rightAnchor.constraint(equalTo: childView.rightAnchor),
imageView.topAnchor.constraint(equalTo: childView.topAnchor),
imageView.bottomAnchor.constraint(equalTo: childView.bottomAnchor),

There is one more thing though - the size of the image view at this point is not what you expect.不过还有一件事——此时图像视图的大小不是您所期望的。 The image view has a height of 100, but its width is still 24, which is the intrinsic size of the "tray" image.图像视图的高度为 100,但其宽度仍为 24,这是“托盘”图像的固有尺寸。 scaleAspectFill does scale the image to the size you want, but the views' widths stay at 24, and since the scaling is done from the centre of the view, the scaled up image appears to be "off centred". scaleAspectFill确实将图像缩放到您想要的大小,但视图的宽度保持在 24,并且由于缩放是从视图的中心完成的,因此放大后的图像似乎“偏离中心”。

I think that in general, you'll just have to manually calculate the width you want:认为一般来说,你只需要手动计算你想要的宽度:

let width = 100 * image.size.width / image.size.height

and constrain both width and height:并约束宽度和高度:

imageView.heightAnchor.constraint(equalToConstant: 100.0),
imageView.widthAnchor.constraint(equalToConstant: width),

However, with SF symbols, you can get a bigger image simply by:但是,使用 SF 符号,您可以通过以下方式获得更大的图像:

let image = UIImage(systemName: "tray", withConfiguration: UIImage.SymbolConfiguration(pointSize: 100))

You don't need any height or width constraints on the image view.您不需要对图像视图进行任何高度或宽度限制。

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

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