使用锚点的自动布局没有按照我的预期方式布置我的视图?

Autolayout using anchors not laying out my views the way I intended?

所以我有一个相当简单的单元格视图,我正在尝试对其进行自定义。我有一堆字段和标签,我想如下图所示进行布局

然而,我最终使用我设置的约束看起来像这样......

indexLabelBackground(圆形)

indexLabel(个数)

repsField(REPS左边0)

repsLabel(REPS 字符串)

dividerLabel(“/”字符串)

weightField(POUNDS 左边的 0)

weightLabel(磅字符串)

我一遍又一遍地查看我的约束,但我找不到任何让我认为我的约束是错误的东西,所以我希望一双新的眼睛能帮助我识别这个令人费解的问题......

P.S. 我什至创建了一个新项目并尝试使用看起来不错的相同约束条件使用故事板重新创建此布局。

private func setupViews() {
    addSubview(indexLabelBackground)
    indexLabelBackground.addSubview(indexLabel)
    addSubview(repsField)
    addSubview(repsLabel)
    addSubview(dividerLabel)
    addSubview(weightField)
    addSubview(weightLabel)

    indexLabelBackground.leftAnchor.constraint(equalTo: leftAnchor, constant: 24).isActive = true
    indexLabelBackground.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
    indexLabelBackground.heightAnchor.constraint(equalToConstant: 24).isActive = true
    indexLabelBackground.widthAnchor.constraint(equalToConstant: 24).isActive = true

    indexLabel.centerXAnchor.constraint(equalTo: indexLabelBackground.centerXAnchor).isActive = true
    indexLabel.centerYAnchor.constraint(equalTo: indexLabelBackground.centerYAnchor).isActive = true

    repsField.leftAnchor.constraint(equalTo: indexLabelBackground.rightAnchor, constant: 8).isActive = true
    repsField.rightAnchor.constraint(equalTo: repsLabel.leftAnchor, constant: -8).isActive = true
    repsField.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

    repsLabel.rightAnchor.constraint(equalTo: dividerLabel.leftAnchor, constant: -16).isActive = true
    repsLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

    dividerLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
    dividerLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

    weightField.leftAnchor.constraint(equalTo: dividerLabel.rightAnchor, constant: 16).isActive = true
    weightField.rightAnchor.constraint(equalTo: weightLabel.leftAnchor, constant: -8).isActive = true
    weightField.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

    weightLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -16).isActive = true
    weightLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
//  weightLabel.widthAnchor.constraint(equalToConstant: 60).isActive = true //note this fixes the problem but forces my label to be a fixed width
    }

所以需要注意的是,如果您查看最后一行,这可能是 "fixed" 以一种骇人听闻的方式,例如向 weightLabel 添加宽度约束。但是我想避免这种情况,因为它看起来很老套并且没有必要使用正确的约束。

问题是您的单元格中有多个元素(字段和标签)可以拉伸以使布局正常工作,而您没有告诉 Auto Layout 哪个那些不要伸展。

您希望标签保持其 固有内容大小 (与显示文本所需的一样大,但不能更大)。您可以通过设置高内容拥抱优先级来指定这一点。默认情况下,当您以编程方式创建 UITextFields 和 UILabels 时,它们的 content hugging prioritylow (250).由于它们都很低,Auto Layout 将以某种未知顺序拉伸它们以使布局正常工作。

我建议添加这 3 行以将 content hugging priority 设置为 high (750) 您的 3 个标签:

repsLabel.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .horizontal)
dividerLabel.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .horizontal)
weightLabel.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .horizontal)

这样,您的标签将始终保持其文本所需的大小,然后它们可以锚定您的布局(双关语)。

I even created a new project and attempted to recreate this layout using storyboards using the same constraints which seemed to look good.

故事板 中,UILabels 的默认 content hugging 优先级 (251) 比UITextFields (250),所以它 正常工作 。令我震惊的是,为什么他们在以编程方式创建时选择全部 low (250)。