动画隐藏 UIStackView 中的子视图超出屏幕

问题描述

我正在尝试为 UIStackView 的排列子视图的隐藏设置动画:

UIView.animate(withDuration: 3,delay: 0) {
    self.stackView.subviews.forEach({ $0.isHidden = true })
    self.stackView.updateConstraintsIfNeeded()
    self.stackView.layoutIfNeeded()
    self.view.layoutIfNeeded()
} completion: { (_) in
    self.children.forEach({ $0.removeFromParent() })
    completion()
}

问题在于动画时视图在屏幕上的宽度扩展(超出屏幕边界)。

这是设置视图的方式:

scrollView = {
    let scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    return scrollView
}()

stackView = {
    let stackView = UIStackView()
    stackView.axis = .vertical
    stackView.distribution = .fill
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    return stackView
}()

contentView = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

contentView.addSubview(stackView)
scrollView.addSubview(contentView)
view.addSubview(scrollView)

scrollView.showsverticalScrollIndicator = false
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

stackView.topAnchor.constraint(equalTo: contentView.topAnchor,constant: 20).isActive = true
stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 20).isActive = true
stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: -20).isActive = true
stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,constant: -50).isActive = true

问题:我怎样才能让它在动画过程中不改变宽度?

解决方法

我不知道这是否是 UIStackView 的一个奇怪问题或者它有什么用途,但是:将“隐形”UIView 放入您的 UIStackView 将解决该问题.标记它,以便在隐藏其他元素时它仍然可见:

let imposterView = UIView()
imposterView.tag = 999
stackView.addArrangedSubview(imposterView)

当然要相应地处理您的隐藏逻辑:

stackView.subviews.forEach({
     if $0.tag != 999 {
         $0.isHidden = true
     }
})