首页 > 解决方案 > UIImageView 上的 directionalLayoutMargins 在水平堆栈视图中不起作用

问题描述

我正在创建一个水平堆栈视图:

let hs = UIStackView(forAutoLayout: ());
hs.axis = .horizontal
hs.spacing = 0
hs.alignment = .top
hs.distribution = .fill
hs.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
hs.isLayoutMarginsRelativeArrangement = true
hs.translatesAutoresizingMaskIntoConstraints = false

然后放置几个孩子:

let label = UILabel(forAutoLayout: ());
hs.addArrangedSubview(label)
let image = UIImageView(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
image.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 64, leading: 0, bottom: 16, trailing: 16)
hs.addArrangedSubview(image)

水平堆栈视图布局看起来不错,但是我在图像中添加了似乎被忽略的布局边距。有没有办法在水平堆栈视图中围绕特定子项设置边距?

编辑:

我知道我可以将 UIImageView 扔到另一个视图中并设置约束。或者更简单,只需使用 EdgeInsets 将其放入另一个堆栈视图中:

let imageStack = UIStackView(forAutoLayout: ());
imageStack.axis = .vertical
imageStack.alignment = .fill
imageStack.distribution = .fill
imageStack.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 64, leading: 0, bottom: 16, trailing: 16)
imageStack.isLayoutMarginsRelativeArrangement = true
imageStack.translatesAutoresizingMaskIntoConstraints = false

imageStack.addArrangedSubview(image)

// add imageStack to horizontal stack view, instead of image
hs.addArrangedSubview(imageStack)

添加到另一个视图或在 UIImageView 中使用图像矩形插入似乎只是为了在视图周围添加边距或填充。来自 Android,我可以在任何视图(包括图像视图)上设置填充和边距,而无需包装在另一个元素中,这对于如此简单的事情来说似乎是一项疯狂的工作。

标签: iosswiftuistackview

解决方案


完全确定你要做什么,但听起来你想要:

  • 水平堆栈视图
  • 左边的标签
  • 右侧的图像视图
  • 图像视图 32x32 其
  • image view top 64-pts from label top

所以,它看起来像这样:

在此处输入图像描述

绿色轮廓显示元素框架(包括堆栈视图)。

如果这是正确的,您可以通过.withAlignmentRectInsets()在运行时修改图像来做到这一点。

这是一个例子:

class StackTestViewController: UIViewController {
    
    let hs = UIStackView()
    let label = UILabel()
    let imageView = UIImageView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        hs.axis = .horizontal
        hs.spacing = 0
        hs.alignment = .top
        hs.distribution = .fill
        hs.isLayoutMarginsRelativeArrangement = true
        hs.translatesAutoresizingMaskIntoConstraints = false
        
        label.text = "Test Label"
        
        hs.addArrangedSubview(label)
        hs.addArrangedSubview(imageView)
        
        view.addSubview(hs)
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            hs.topAnchor.constraint(equalTo: g.topAnchor, constant: 80.0),
            hs.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
            imageView.widthAnchor.constraint(equalToConstant: 32.0),
            
            // we want the imageView to be 64-pts taller than its width
            imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, constant: 64)
            
        ])
        
        if let img = UIImage(named: "swiftBlue64x64") {
            // use withAlignmentRectInsets to create a new image with 64-pts "empty space" on top
            imageView.image = img.withAlignmentRectInsets(UIEdgeInsets(top: -64, left: 0, bottom: 0, right: 0))
        }

        // so we can see the label frame
        label.backgroundColor = .yellow
        
    }
    
}

我使用了这个 64x64 像素的图像:

在此处输入图像描述


编辑

来自 Apple 的文档:

讨论

使用此属性可指定此视图的边缘与其子视图之间的所需空间量(以磅为单位)。

因此,您可以将其应用于UIStackView 整体或具有子视图的视图。这应该解释为什么它不能应用于UIImageView(无子视图)。


推荐阅读