Recentemente, lutei com erros de layout automático ao ocultar um UIStackView
. Em vez de fazer um monte de guarda de livros e empacotamento UIViews
, optei por criar uma saída para o meu parentStackView
e para as crianças que quero ocultar / mostrar.
@IBOutlet weak var parentStackView: UIStackView!
@IBOutlet var stackViewNumber1: UIStackView!
@IBOutlet var stackViewNumber2: UIStackView!
No storyboard, minha pilha pai se parece com:
Ele tem 4 filhos e cada um deles tem várias visualizações de pilha dentro deles. Quando você oculta uma visualização de pilha, se ela tiver elementos de interface do usuário que também são visualizações de pilha, você verá um fluxo de erros de layout automático. Em vez de me esconder, optei por removê-los.
No meu exemplo, parentStackViews
contém uma matriz dos 4 elementos: Top Stack View, StackViewNumber1, Stack View número 2 e botão Stop. Seus índices arrangedSubviews
são 0, 1, 2 e 3, respectivamente. Quando desejo ocultar um, simplesmente o removo do parentStackView's
arrangedSubviews
array. Como não é fraco, ele permanece na memória e você pode simplesmente colocá-lo de volta no índice desejado mais tarde. Não estou reinicializando-o, então ele permanece até que seja necessário, mas não incha a memória.
Então, basicamente, você pode ...
1) Arraste IBOutlets para a pilha pai e os filhos que deseja ocultar / mostrar para o storyboard.
2) Quando você quiser ocultá-los, remova a pilha que deseja ocultar do parentStackView's
arrangedSubviews
array.
3) Ligue self.view.layoutIfNeeded()
com UIView.animateWithDuration
.
Observe que os dois últimos stackViews não são weak
. Você precisa mantê-los por perto para quando você os revelar.
Digamos que eu queira ocultar stackViewNumber2:
parentStackView.removeArrangedSubview(stackViewNumber2)
stackViewNumber2.removeFromSuperview()
Em seguida, anime-o:
UIView.animate(withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 2.0,
initialSpringVelocity: 10.0,
options: [.curveEaseOut],
animations: {
self.view.layoutIfNeeded()
},
completion: nil)
Se você quiser "mostrar" um stackViewNumber2
depois, basta inseri-lo no parentStackView
arrangedSubViews
índice desejado e animar a atualização.
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)
Descobri que isso é muito mais fácil do que fazer contabilidade sobre as restrições, mexer nas prioridades etc.
Se você deseja ocultar algo por padrão, pode simplesmente colocá-lo no storyboard, removê-lo viewDidLoad
e atualizá-lo sem usar a animação view.layoutIfNeeded()
.