【问题标题】:iOS AutoLayout constraint `lessThanOrEqualToConstant` doesn't workiOS AutoLayout 约束`lessThanOrEqualToConstant` 不起作用
【发布时间】:2018-05-27 04:05:08
【问题描述】:

我在UIStackView 内遇到UIView 的自动布局约束问题。

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

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?)
  • 什么意思?我将value: CGFloat 传递给约束...
  • 答案取决于您尝试实现的确切行为,但您可以尝试将视图的verticalCompressionResistance 设置为 1000。这应该会使您的间距视图仅在需要时缩小。您还可以将 heightConstraint 设为必需,而不仅仅是高优先级。
  • lessThanOrEqualToConstant 约束不足以使自动布局知道实际高度,但仅当视图上下钩到 UILabel 等可调整大小的元素时才会起作用
  • @DavidGanster,垂直压缩阻力不起作用。实际上,我不明白为什么应该这样做,因为它用于具有固有大小的视图。

标签: ios swift autolayout uistackview


【解决方案1】:
**//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

【讨论】:

  • 请解释你的答案。
【解决方案2】:

代码有效,因为 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),视图并没有变小并且包含与以前相同的大小。
  • 尝试对高度限制使用较低的优先级,例如:heightConstraint2.priority = UILayoutPriority(rawValue: 140)
  • 我刚刚检查了您的解决方案它确实有帮助!谢谢!
【解决方案3】:

在小于 Constaint 的布局中看到这个错误

但是像 UILabel 一样可以调整顶部和底部的大小,它可以工作

【讨论】:

  • 但对我来说这没有意义。起初,我有一组视图,我想用空格分隔它们。每个空间都是UIStackView 中的一个排列的子视图。其次,在堆栈视图中,任何视图都不需要了解其他排列的子视图。最后,我的问题是运行时,它不会在控制台中产生任何自动布局错误。
  • 为什么不尝试在运行时枚举约束并根据帧计算随意更改常量
  • 这是选项之一,我同意。虽然,这似乎是 AutoLayout 应该处理的事情......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多