ios - how - stackview buttons
UIStackView Ocultar Ver AnimaciĆ³n (5)
Extensión Swift 4:
// MARK: - Show hide animations in StackViews
extension UIView {
func hideAnimated(in stackView: UIStackView) {
if !self.isHidden {
UIView.animate(
withDuration: 0.35,
delay: 0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
self.isHidden = true
stackView.layoutIfNeeded()
},
completion: nil
)
}
}
func showAnimated(in stackView: UIStackView) {
if self.isHidden {
UIView.animate(
withDuration: 0.35,
delay: 0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
self.isHidden = false
stackView.layoutIfNeeded()
},
completion: nil
)
}
}
}
En iOS 11, el comportamiento de la animación oculta dentro de
UIStackView
ha cambiado, pero no he podido encontrar esto documentado en ningún lado.
iOS 10
iOS 11
El código en ambos es este:
UIView.animate(withDuration: DiscoverHeaderView.animationDuration,
delay: 0.0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
clear.isHidden = hideClear
useMyLocation.isHidden = hideLocation
},
completion: nil)
¿Cómo restauro el comportamiento anterior en iOS 11?
Quiero compartir esta función que es buena para ocultar y mostrar muchas vistas en
UIStackView
, porque con todo el código que usé antes no funcionó bien porque uno necesita eliminar la animación de algunas capas:
extension UIStackView {
public func make(viewsHidden: [UIView], viewsVisible: [UIView], animated: Bool) {
let viewsHidden = viewsHidden.filter({ $0.superview === self })
let viewsVisible = viewsVisible.filter({ $0.superview === self })
let blockToSetVisibility: ([UIView], _ hidden: Bool) -> Void = { views, hidden in
views.forEach({ $0.isHidden = hidden })
}
// need for smooth animation
let blockToSetAlphaForSubviewsOf: ([UIView], _ alpha: CGFloat) -> Void = { views, alpha in
views.forEach({ view in
view.subviews.forEach({ $0.alpha = alpha })
})
}
if !animated {
blockToSetVisibility(viewsHidden, true)
blockToSetVisibility(viewsVisible, false)
blockToSetAlphaForSubviewsOf(viewsHidden, 1)
blockToSetAlphaForSubviewsOf(viewsVisible, 1)
} else {
// update hidden values of all views
// without that animation doesn''t go
let allViews = viewsHidden + viewsVisible
self.layer.removeAllAnimations()
allViews.forEach { view in
let oldHiddenValue = view.isHidden
view.layer.removeAllAnimations()
view.layer.isHidden = oldHiddenValue
}
UIView.animate(withDuration: 0.3,
delay: 0.0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
blockToSetAlphaForSubviewsOf(viewsVisible, 1)
blockToSetAlphaForSubviewsOf(viewsHidden, 0)
blockToSetVisibility(viewsHidden, true)
blockToSetVisibility(viewsVisible, false)
self.layoutIfNeeded()
},
completion: nil)
}
}
}
Solo tuve el mismo problema.
La solución es agregar
stackView.layoutIfNeeded()
dentro del bloque de animación.
Donde
stackView
es el contenedor de los elementos que desea ocultar.
UIView.animate(withDuration: DiscoverHeaderView.animationDuration,
delay: 0.0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
clear.isHidden = hideClear
useMyLocation.isHidden = hideLocation
stackView.layoutIfNeeded()
},
completion: nil)
No estoy seguro de por qué esto es repentinamente un problema en iOS 11, pero para ser justos, siempre ha sido el enfoque recomendado.
Solo usa:
UIView.animate(withDuration: 0.3){
viewInsideStackView.hidden = true //or false
}
Extensión para ocultar / mostrar elementos individuales
No está 100% relacionado, pero si está buscando una manera concisa de ocultar elementos individuales de
UIView
(ya sea en una vista de pila o en cualquier otro lugar), puede usar esta extensión simple que hice:
extension UIView {
func isHiddenAnimated(value: Bool, duration: Double = 0.2) {
UIView.animate(withDuration: duration) { [weak self] in self?.isHidden = value }
}
}
Lo uso para ocultar / mostrar convenientemente elementos con animación en una vista de pila con una sola línea de código. Ejemplo:
validatableButton.isHiddenAnimated(value: false)