动画子视图 AutoLayout 约束变化

Animate subview AutoLayout constraint changes

许多关于动画 AutoLayout 约束的教程建议更新约束的常量 属性,然后在动画块中调用 layoutIfNeeded()

我的情况有点棘手。 我有一个包含 3 个子视图的视图。这个父视图的高度不是固定的——它是作为它的子视图的高度的总和来计算的。 在某些情况下,我要求这 3 个子视图之一切换其高度(它在 0 到 30 之间变化,即我想平滑地隐藏和显示它)。 代码类似这样:

// In superview
subview1.isVisibleInContext = !subview1.isVisibleInContext

// In subview
class MySubview: UIView {
    @IBOutlet var heightConstraint: NSLayoutConstraint!

    var isVisibleInContext = false {
        didSet {
            updateHeight()
        }
    }

    func toggleHeight() {
        let newHeight = isVisibleInContext ? 30 : 0
        layoutIfNeeded()
        heightConstraint.constant = newHeight
        UIView.animate(withDuration: 0.8) {
            self.layoutIfNeeded()
        }
    }
}

不幸的是,这并不像我预期的那样有效。 我可以看到子视图高度的平滑变化,但是在我为子视图高度约束设置新值后立即重新计算父视图的高度。

我想看到父视图的高度随着其子视图的增长或减小而逐渐变化increasing/decreasing。

请有人指出我正确的方向。感谢任何帮助。

非常感谢!

动画块应该在包含 3 MySubviewsUIView 中。在 MySubview class 中,您只更新高度约束的常量:

在子视图中

func toggleHeight() {
   let newHeight = isVisibleInContext ? 30 : 0
   heightConstraint.constant = newHeight
}

然后在包含 3 MySubviewsUIView 中设置动画更改:

在超级视图中

func toggleHeight(with subview: MySubview) {
   subview.toggleHeight()
   UIView.animate(withDuration: 0.8) {
      self.view.layoutIfNeeded()
   }
}

首先,我的方法不正确的是执行 self.layoutIfNeeded()。在调查了这个问题后,我了解到我必须在 superivew 上执行它,如下所示:

self.superview?.layoutIfNeeded()

这也没有成功是有原因的。这种情况下的主要问题是内部有 3 个子视图的视图本身就是视图的子视图。所以为了让它工作,我必须使用以下代码:

self.superview?.superview?.layoutIfNeeded()

子视图必须知道视图的层次结构绝对不好,但是它有效。