我最近在隐藏 UIStackView 时遇到了自动布局错误。我没有在UIViews 中做一堆簿记和包装堆栈,而是选择为我的parentStackView 创建一个插座,并为我想要隐藏/取消隐藏的孩子创建一个插座。
@IBOutlet weak var parentStackView: UIStackView!
@IBOutlet var stackViewNumber1: UIStackView!
@IBOutlet var stackViewNumber2: UIStackView!
在故事板中,我的 parentStack 如下所示:
它有 4 个孩子,每个孩子里面都有一堆堆栈视图。当您隐藏堆栈视图时,如果它的 UI 元素也是堆栈视图,您将看到一连串自动布局错误。我没有隐藏,而是选择删除它们。
在我的示例中,parentStackViews 包含 4 个元素的数组:顶部堆栈视图、堆栈视图编号 1、堆栈视图编号 2 和停止按钮。它们在arrangedSubviews 中的索引分别为 0、1、2 和 3。当我想隐藏一个时,我只需将其从 parentStackView's arrangedSubviews 数组中删除。由于它不弱,它会在内存中徘徊,您可以稍后将其放回所需的索引。我没有重新初始化它,所以它只是挂起直到需要它,但不会膨胀内存。
所以基本上,你可以...
1) 将父堆栈的 IBOutlets 和要隐藏/取消隐藏的子堆栈拖到情节提要中。
2) 当你想隐藏它们时,从parentStackView'sarrangedSubviews数组中移除你想隐藏的栈。
3) 使用UIView.animateWithDuration 致电self.view.layoutIfNeeded()。
注意最后两个 stackViews 不是weak。当您取消隐藏它们时,您需要保留它们。
假设我想隐藏 stackViewNumber2:
parentStackView.removeArrangedSubview(stackViewNumber2)
stackViewNumber2.removeFromSuperview()
然后对其进行动画处理:
UIView.animate(withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 2.0,
initialSpringVelocity: 10.0,
options: [.curveEaseOut],
animations: {
self.view.layoutIfNeeded()
},
completion: nil)
如果您想稍后“取消隐藏”stackViewNumber2,只需将其插入所需的parentStackView arrangedSubViews 索引并为更新设置动画。
parentStackView.removeArrangedSubview(stackViewNumber1)
stackViewNumber1.removeFromSuperview()
parentStackView.insertArrangedSubview(stackViewNumber2, at: 1)
// Then animate it
UIView.animate(withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 2.0,
initialSpringVelocity: 10.0,
options: [.curveEaseOut],
animations: {
self.view.layoutIfNeeded()
},
completion: nil)
我发现这比记录约束、摆弄优先级等要容易得多。
如果您想要默认隐藏某些内容,您可以将其放置在情节提要上,然后在 viewDidLoad 中将其删除,然后使用 view.layoutIfNeeded() 在不使用动画的情况下进行更新。