Встроенная анимация UIStackView
используется, когда упорядоченное подпредставление показано / скрыто, может работать хорошо - и это может быть не так уж и хорошо.
Одна из ключевых вещей, связанных с представлением стекаdo is организовать свои подпредставления . Конечно, часто также используют ширину и высоту подпредставлений, чтобы определить ширину и высоту стекового представления. Таким образом, мы можем получить неопределенные состояния, и анимация, как вы видели, становится «вонючей».
Дайте этому попытку (весь код, не @IBOutlets
или @IBActions
, поэтому просто назначьтеконтроллер представления к этому классу):
class StackShowHideViewController: UIViewController {
// UIButton
let btn: UIButton = {
let v = UIButton()
v.translatesAutoresizingMaskIntoConstraints = false
v.setTitle("Tap Me", for: .normal)
v.backgroundColor = .red
return v
}()
// vertical UIStackView
let stackView: UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = false
v.axis = .vertical
v.alignment = .fill
v.distribution = .fill
v.spacing = 8
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
// add elements to view
view.addSubview(btn)
view.addSubview(stackView)
NSLayoutConstraint.activate([
// constrain button 20-pts from top, centered horizontally
btn.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
btn.centerXAnchor.constraint(equalTo: view.centerXAnchor),
// constrain stack view 20-pts from bottom of button
// centered horizontally
// width constrained to 160-pts
stackView.topAnchor.constraint(equalTo: btn.bottomAnchor, constant: 20.0),
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.widthAnchor.constraint(equalToConstant: 160.0),
])
// add 5 UILabels to the stack view
for i in 1...5 {
let v = UILabel()
v.backgroundColor = .yellow
v.text = "This is Label \(i)"
v.textAlignment = .center
v.translatesAutoresizingMaskIntoConstraints = false
// inititially hidden
v.isHidden = true
// add label to stack view
stackView.addArrangedSubview(v)
// constrain label widths to width of stack view
v.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true
}
btn.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)
}
public func setStackViewHidden(_ isHidden: Bool, animated: Bool) {
stackView.arrangedSubviews.forEach ({ subview in
if animated {
UIView.animate(withDuration: 0.3) {
subview.isHidden = isHidden
}
} else {
subview.isHidden = isHidden
}
})
}
@objc func didTap(_ sender: Any) {
// if labels are hidden, show them
// else, hide them
var h = true
if let v = stackView.arrangedSubviews.first {
h = v.isHidden
}
setStackViewHidden(!h, animated: true)
}
}