【问题标题】:View height changes unexpectedly (Swift)视图高度意外更改(Swift)
【发布时间】:2021-02-08 20:49:48
【问题描述】:

我已经设置了约束,允许 UIView cv1 根据屏幕大小动态改变高度,cv2cv3 的高度是固定的。

由于某种原因,当我如图所示运行时,cv3 的视图高度变为 172。

在一个或另一个或两个中使用原始的cv3.heightAnchor.constraint(equalToConstant: cv3Height),我遇到了与here 相同的问题(这对cv2 非常有效),附加效果是我用h3, 替换它(窄或宽)视图仅在该方向跳转到 172,但也给了我冲突约束消息。

没有运气,我删除了所有其他约束。

这是另一个错误吗?如果是这样,是否有解决方法?

这里是一个最小化的函数,整个函数如下:

func setConstraints() {
            
    cv3.translatesAutoresizingMaskIntoConstraints = false

    let g = view.safeAreaLayoutGuide
    
    let cv3Height: CGFloat = 125
    let h3 = cv3.heightAnchor.constraint(equalToConstant: cv3Height)
    h3.priority = .defaultHigh
    
    narrowConstraints = [
        // set cv3 height
        //cv3.heightAnchor.constraint(equalToConstant: cv3Height),
        h3, 

        // lock left, right and bottom to safe area
        cv3.leadingAnchor.constraint(equalTo: g.leadingAnchor),
        cv3(equalTo: g.trailingAnchor),
        cv3(equalTo: g.bottomAnchor),
    ]
    
    wideConstraints = [
        // set cv3 height
        //cv3.heightAnchor.constraint(equalToConstant: cv3Height),
        h3, 

        // lock bottom and right side of cv3 to safe area
        cv3(equalTo: g.trailingAnchor),
        cv3(equalTo: g.bottomAnchor),
        
        // make them all equal widths
        cv2.widthAnchor.constraint(equalTo: cv1.widthAnchor),
        cv3.widthAnchor.constraint(equalTo: cv2.widthAnchor),
    ]

    
    // activate the commonConstraints
    NSLayoutConstraint.activate(commonConstraints)
    
    if view.frame.width > view.frame.height {
        // wider than tall, so "landscape"
        NSLayoutConstraint.deactivate(narrowConstraints)
        NSLayoutConstraint.activate(wideConstraints)
    } else {
        // taller than wide
        NSLayoutConstraint.deactivate(wideConstraints)
        NSLayoutConstraint.activate(narrowConstraints)
    }
    
}

这是整个函数:

func setConstraints() {
    
    cv1.translatesAutoresizingMaskIntoConstraints = false
    cv2.translatesAutoresizingMaskIntoConstraints = false
    cv3.translatesAutoresizingMaskIntoConstraints = false
    
    let g = view.safeAreaLayoutGuide
    
    let cv2Height: CGFloat = 190
    let h2 = cv2.heightAnchor.constraint(equalToConstant: cv2Height)
    h2.priority = .defaultHigh
    
    let cv3Height: CGFloat = 125
    let h3 = cv3.heightAnchor.constraint(equalToConstant: cv3Height)
    h3.priority = .defaultHigh
    
    narrowConstraints = [
        
        // lock top, left and right to safe area
        cv1.topAnchor.constraint(equalTo: g.topAnchor),
        cv1.leadingAnchor.constraint(equalTo: g.leadingAnchor),
        cv1.trailingAnchor.constraint(equalTo: g.trailingAnchor),
        
        // set cv2 height
        //cv2.heightAnchor.constraint(equalToConstant: cv2Height),
        h2,

        // lock left and right to safe area
        cv2.leadingAnchor.constraint(equalTo: g.leadingAnchor),
        cv2.trailingAnchor.constraint(equalTo: g.trailingAnchor),
        
        // lock top of cv2 to bottom of cv1
        cv2.topAnchor.constraint(equalTo: cv1.bottomAnchor),
        // lock bottom of cv2 to top of cv3
        cv2.bottomAnchor.constraint(equalTo: cv3.topAnchor),
        
        // set cv3 height
        //cv3.heightAnchor.constraint(equalToConstant: cv3Height),
        h3, 

        // lock left, right and bottom to safe area
        cv3.leadingAnchor.constraint(equalTo: g.leadingAnchor),
        cv3(equalTo: g.trailingAnchor),
        cv3(equalTo: g.bottomAnchor),
    ]
    
    wideConstraints = [
        
        // lock top, bottom, and left to safe area
        cv1.topAnchor.constraint(equalTo: g.topAnchor),
        cv1.bottomAnchor.constraint(equalTo: g.bottomAnchor),
        cv1.leadingAnchor.constraint(equalTo: g.leadingAnchor),
        // lock right side of cv1 to left side of cv2
        cv1.trailingAnchor.constraint(equalTo: cv2.leadingAnchor),
        
        // lock right side of cv2 to safe area
        cv2.trailingAnchor.constraint(equalTo: g.trailingAnchor),
        // lock top of cv2 to safe area
        cv2.topAnchor.constraint(equalTo: g.topAnchor),
        // lock bottom of cv2 to top of cv3
        cv2.bottomAnchor.constraint(equalTo: cv3.topAnchor),
        
        // set cv3 height
        //cv3.heightAnchor.constraint(equalToConstant: cv3Height),
        h3, 

        // lock bottom and right side of cv3 to safe area
        cv3(equalTo: g.trailingAnchor),
        cv3(equalTo: g.bottomAnchor),
        
        // make them all equal widths
        cv2.widthAnchor.constraint(equalTo: cv1.widthAnchor),
        cv3.widthAnchor.constraint(equalTo: cv2.widthAnchor),
    ]

    
    // activate the commonConstraints
    NSLayoutConstraint.activate(commonConstraints)
    
    if view.frame.width > view.frame.height {
        // wider than tall, so "landscape"
        NSLayoutConstraint.deactivate(narrowConstraints)
        NSLayoutConstraint.activate(wideConstraints)
    } else {
        // taller than wide
        NSLayoutConstraint.deactivate(wideConstraints)
        NSLayoutConstraint.activate(narrowConstraints)
    }
    
}

【问题讨论】:

  • 您是否检查了 View Debugger 是否有帮助?
  • 我已经查看过了,但什么也没看到。 (我可能太新了,无法理解我在寻找什么。)
  • 我刚刚发现,如果我在 IB 中设置高度并从 func 中删除约束,它就可以工作!不是我正在寻找的解决方案,但如果让我暂时进入下一阶段,我会接受它!
  • 我还发现cv3 将始终介于 172 和 208 之间。如果我将其高度设置为 30,它将最终为 172;如果我将其设置为 500,它将以 208 结束。但是,介于“似乎”之间的任何东西都可以正常工作 - 将其设置为 187 最终会在 187 结束。
  • (提示:要实现inline code formatting,只需要单个反引号。单引号更容易添加和编辑。三元组仅用于块格式化,而四元组永远不需要 - 即使它们仍然有效)。

标签: ios swift


【解决方案1】:

我看起来问题是每次调用函数时,您都在创建新的约束,但没有停用上次运行时的旧约束。

例如,第一次调用它时,它将创建一组宽和窄约束并激活宽集。下次调用它时,它将创建一组新的宽约束和窄约束,并激活第二组的窄约束,而不会停用第一组的宽约束。您对停用它的调用将在第二组上调用,这将生效。

我猜想冲突约束消息显示了第一组中尚未停用的约束。


我要做的是将你的函数分成两个单独的函数。

创建一个setupConstraints 函数,该函数仅创建约束数组并仅激活commonConstraints。重要的部分是确保这个函数只被调用一次。

创建一个 activateConstraintsForOrientation 函数,该函数仅在函数底部包含 if 语句。然后,只要您认为方向发生了变化,就可以调用此函数。

【讨论】:

  • 我调用该函数的唯一一次是在override func viewDidLoad()
  • 但为了确定起见,我尝试了两件事:将其移至override func viewWillAppear,并在函数顶部添加NSLayoutConstraint.deactivate(narrowConstraints) NSLayoutConstraint.deactivate(wideConstraints),但均未解决问题。
  • 你能发布你收到的不可满足的约束警告吗?这将是很多有用的信息。
  • 我没有收到任何警告,因为我更改了处理 cv2cv3 高度锚的优先级。警告似乎是一个错误(我已经报告过),由过渡期间状态栏的出现引起。
  • 但是你可以看到我在这里收到的警告:stackoverflow.com/questions/64296915/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 2021-04-23
  • 1970-01-01
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多