iOS AutoLayout约束`lessThanOrEqualToConstant`无效。

4

我有一个关于UIStackViewUIView的自动布局约束问题。

我的目标是创建一个视图:

private static func makeSpace(with value: CGFloat) -> UIView {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = true

    let heightConstraint =  view.heightAnchor.constraint(lessThanOrEqualToConstant: value)
    heightConstraint.priority = UILayoutPriorityDefaultHigh

    NSLayoutConstraint.activate([
        view.widthAnchor.constraint(equalToConstant: 295),
        heightConstraint
    ])

    return view
}

我想将此视图作为排列的子视图添加到 UIStackView 中,作为其他 UIStackView 排列的子视图之间的空间。

当我使用可视化检查器检查这些视图时,我的空间视图高度为 0。然而,当我将约束更改为 equalToConstant 时,高度会正确计算。

我想使用 lessThanOrEqualToConstant,以便在屏幕布局太小无法适应正确大小时,允许这些空间缩小。

是否有其他人遇到过这个问题?


你不应该在那个字段里输入一些值吗?(我猜是 CGFloat 类型的值?) - Ashish Bahl
你是什么意思?我正在将 value: CGFloat 传递给约束... - Daumantas Versockas
答案取决于您要实现的确切行为,但您可以尝试将视图的 verticalCompressionResistance 设置为 1000。这应该只在需要时使您的间隔视图收缩。 您还可以使 heightConstraint 变为必须而不仅仅是高优先级。 - David Ganster
lessThanOrEqualToConstant 约束不足以让自动布局知道实际高度,但只有当视图连接到可调整大小的元素(如 UILabel)的顶部和底部时才起作用。 - Shehata Gamal
@DavidGanster,垂直压缩阻力不起作用。 实际上,我不明白为什么它应该起作用,因为它用于具有内在大小的视图。 - Daumantas Versockas
3个回答

0

在小于Constaint时出现的布局错误,请参见以下内容 输入图像描述

但与可调整大小的顶部和底部标签类似,它可以正常工作 输入图像描述


但对我来说这没有意义。首先,我有一组视图,我想用空格分隔。每个空格都是UIStackView中排列的子视图。其次,在堆栈视图内,任何视图都不需要知道其他排列的子视图的任何信息。最后,我的问题是运行时问题,并且在控制台中不会生成任何自动布局错误。 - Daumantas Versockas
为什么不尝试在运行时枚举约束,并根据框架计算随意更改常量呢? - Shehata Gamal
这是其中一个选项,我同意。不过,这似乎是AutoLayout应该处理的事情... - Daumantas Versockas

0
代码可行,因为0实际上小于或等于295。 如果您希望根据堆栈中的其他视图使其不超过295,则需要另一个限制条件告诉它在可能的情况下扩展到295:
private static func makeSpace(with value: CGFloat) -> UIView {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = true

    // this keeps it under the value, we want this to be enforced, so priority stays `required`
    let heightConstraint1 =  view.heightAnchor.constraint(lessThanOrEqualToConstant: value)

    // this constraint will drive the size (the other one is just correcting it)
    let heightConstraint2 =  view.heightAnchor.constraint(equalToConstant: value)
    // modify this priority according to compression resistance of the other views
    heightConstraint2.priority = UILayoutPriority(rawValue: 240)

    NSLayoutConstraint.activate([
        view.widthAnchor.constraint(equalToConstant: 295),
        heightConstraint1,
        heightConstraint2
    ])

    return view
}

第一个约束条件使得空间保持在value常量下(例如295)。这个约束条件必须具有required优先级,因为你不想以任何方式扩展这个高度。
第二个约束条件告诉它保持高度等于value。但是它的优先级较低。所以其他约束条件可以覆盖它。如果发生这种情况,自动布局系统将尝试尽可能接近实现它 - 所以如果它不能是295,但它可以是230,那么就会发生这种情况。
旁注:
如果您不关心将其扩展到比value(例如295)更大的值,则根本不需要第一个约束条件。我之所以保留它,是因为我认为这是必须保持的空间限制。
另一边注: CompressionResistancePriorityContentHuggingPriority适用于具有固有尺寸的视图,而这不适用于UIView

谢谢您的回答。我已经测试了您的解释。目前视图的高度是非零的。然而,当屏幕布局较小(例如iPhone SE)时,视图并没有变小,仍然保持之前的大小。 - Daumantas Versockas
尝试为高度约束使用较低的优先级,例如:heightConstraint2.priority = UILayoutPriority(rawValue: 140) - Milan Nosáľ
2
我刚刚检查了你的解决方案,确实有帮助!谢谢! - Daumantas Versockas

0
**//1** 

 let child = UIView()
  child.translatesAutoresizingMaskIntoConstraints = false
  child.backgroundColor = .red
  view.addSubview(child)


**//2**

  child.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
  child.bottomAnchor.constraint(equalTo:     view.safeAreaLayoutGuide.bottomAnchor).isActive = true
  child.widthAnchor.constraint(equalToConstant: 128).isActive = true
  child.centerXAnchor.constraint(equalTo:   view.safeAreaLayoutGuide.centerXAnchor).isActive = true

请在回答中提供解释。 - kk.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接