UIImageView 上的 directionalLayoutMargins 在水平堆栈视图中不起作用

Posted

技术标签:

【中文标题】UIImageView 上的 directionalLayoutMargins 在水平堆栈视图中不起作用【英文标题】:directionalLayoutMargins on UIImageView not working inside horizontal stack view 【发布时间】:2020-08-24 21:45:42 【问题描述】:

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

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,我可以在任何视图(包括图像视图)上设置填充和边距,而无需包装在另一个元素中,这对于如此简单的事情来说似乎是一项疯狂的工作。

【问题讨论】:

您是否要向图像视图“添加顶部填充”?如果是这样,那么这种方法是不正确的。见:***.com/questions/32551890/… 因此,要向图像视图添加插图或边距,您必须将其放在另一个视图中。看起来很荒谬,感谢 ios 【参考方案1】:

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

水平堆栈视图 左侧标签 右侧的图像视图 图像视图 32x32 其 图像视图顶部距离标签顶部 64 分

所以,它看起来像这样:

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

如果正确,您可以使用.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(无子视图)。

【讨论】:

谢谢。我更新了这个问题,我想它真的是关于我认为我对 directionalLayoutMargins 的误解。似乎我应该能够在 ImageView 上设置边距。我知道我可以将 UIIImageView 包装在另一个视图中,或者弄乱 ImageView 中的图像插图。但这似乎是一种解决方法,因为人们不能简单地在 ImageView 周围添加边距。

以上是关于UIImageView 上的 directionalLayoutMargins 在水平堆栈视图中不起作用的主要内容,如果未能解决你的问题,请参考以下文章