UIStackView与UIImageView没有按预期处理约束

时间:2018-04-19 18:34:59

标签: swift uiimageview uistackview

我在UIStackView(垂直)中有一个UIStackView(水平)addArrangedSubview。

水平视图有3个单元格:第一个是带有UILabel的addArrangedSubview,第二个有UIImageView(宽度和高度常量约束以保持我想要的大小)。第三个单元格是带有UILabel的addArrangedSubview。 我希望UIStackView适合整个屏幕宽度

不幸的是,结果如下:

enter image description here

我的代码如下:

    let sv = UIStackView()
    sv.axis = .horizontal
    sv.alignment = .center
    sv.distribution = .fill
    sv.spacing = 10

    // Name
        var label = UILabel()
        label.numberOfLines = 0
        label.textAlignment = .natural
        label.text = poi.name
        label.font = UIFont.preferredFont(forTextStyle: .title1)
        sv.addArrangedSubview(label)

    // Open/closed
        let open = true
        let _ = addImageView(open ? #imageLiteral(resourceName: "Open") : #imageLiteral(resourceName: "Closed"), to: sv)

    // Stars
        let maxRank = 5
        let rank = 3
        label = UILabel()
        label.numberOfLines = 0
        label.textAlignment = .natural
        label.text = "".padding(right: rank, withPad: "★").padding(right: maxRank-rank, withPad: "☆")
        sv.addArrangedSubview(label)

    verticalStackView.addArrangedSubview(sv)

我的工具功能如下:

    let w: CGFloat = 32.0
    let r = CGRect(x: 0, y: 0, width: w, height: w)

    func addImageView(_ image: UIImage, to sv: UIStackView) {
        let iv = UIImageView()
        iv.contentMode = .scaleAspectFit
        iv.image = image

        //iv.translatesAutoresizingMaskIntoConstraints = true
        let constraints = [
            iv.widthAnchor .constraint(equalToConstant: w),
            iv.heightAnchor.constraint(equalToConstant: w)
        ]
        //let _ = constraints.map { $0.priority = .defaultHigh }
        NSLayoutConstraint.activate(constraints)
        /*
        iv.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000.0), for: .horizontal)
        iv.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000.0), for: .vertical)
        */
        if true {
            sv.addArrangedSubview(iv)
        } else {
            let v = UIView()
            v.layer.borderColor = UIColor.red.cgColor
            v.layer.borderWidth = 1
            v.addSubview(iv)
            sv.addArrangedSubview(v)
        }
    }

注1:我做了一些实验,因此注释了代码。

注意2:屏幕截图上的红色条是我的手绘图,以便于理解细胞的布局。

[UPDATE]

为了清理事情,弄乱了一切,是我添加到UIImageView的约束,没有一个,一切都好。我添加约束的原因是保持UIImageView的平方和正确的尺寸。 出于这个原因,我添加了一个UIView作为中间元素,以吸收UIStackView约束设置到内部元素的强度(因此if false代码)。但后来我需要在UIView中添加额外的约束来使UIImageView居中,这听起来有点过度使用了布局系统。当然 我可能错过了一些简化整个事情的东西。

2 个答案:

答案 0 :(得分:0)

你可以吗? - 尝试为Root-StackView添加约束,尾随,顶部,底部和前导等于常量0。 - 尝试使用.fill而不是.center更改Root-StackView的对齐方式。

  • 如果您想使标签更加灵活,请使抗压性和上下文拥抱属性的价值(通常为248,748)远低于其他(251,250,750)。

感谢, Ĵ

答案 1 :(得分:0)

我终于解决了这个问题:我将阻力压缩优先级更改为.required标签和UIImageView:

label.setContentCompressionResistancePriority(UILayoutPriority.required, for: .horizontal)

现在,相同的代码片段如下:

// Name
    var label = UILabel()
    label.numberOfLines = 0
    label.textAlignment = .natural
    label.text = poi.name
    label.font = UIFont.preferredFont(forTextStyle: .title1)
    label.setContentCompressionResistancePriority(UILayoutPriority.required, for: .horizontal)

    sv.addArrangedSubview(label)

// Open/closed
    let open = true
    let _ = addImageView(open ? #imageLiteral(resourceName: "Open") : #imageLiteral(resourceName: "Closed"), to: sv)

// Stars
    let maxRank = 5
    let rank = 3
    label = UILabel()
    label.numberOfLines = 0
    label.textAlignment = .natural
    label.text = "".padding(right: rank, withPad: "★").padding(right: maxRank-rank, withPad: "☆")
    label.setContentCompressionResistancePriority(UILayoutPriority.required, for: .horizontal)

    sv.addArrangedSubview(label)

verticalStackView.addArrangedSubview(sv)

    func addImageView(_ image: UIImage, to sv: UIStackView) {
        let iv = UIImageView()
        iv.contentMode = .scaleAspectFit
        iv.image = image

        NSLayoutConstraint.activate([
            iv.widthAnchor .constraint(equalToConstant: w),
            iv.heightAnchor.constraint(equalToConstant: w)
        ])

        iv.setContentCompressionResistancePriority(UILayoutPriority.required, for: .horizontal)
        iv.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)

        sv.addArrangedSubview(iv)
    }