在iOS 11中,UIStackView
内的隐藏动画的行为已经改变,但我无法在任何地方找到此文档。
iOS 10
iOS 11
两者中的代码是:
UIView.animate(withDuration: DiscoverHeaderView.animationDuration,
delay: 0.0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
clear.isHidden = hideClear
useMyLocation.isHidden = hideLocation
},
completion: nil)
如何在iOS 11上恢复以前的行为?
答案 0 :(得分:75)
刚刚遇到同样的问题。
修复是在动画块中添加stackView.layoutIfNeeded()
。 stackView
是您希望隐藏的项目的容器。
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)
不确定为什么这在iOS 11中突然出现问题,但公平地说它一直是推荐的方法。
答案 1 :(得分:4)
在接受的答案的注释中已经提到了此问题,但这是我的问题,这里没有任何答案,所以
请确保从不永远不要在已隐藏的视图上设置isHidden = true
。这会弄乱堆栈视图。
答案 2 :(得分:3)
Swift 4扩展程序:
src/test/resources
答案 3 :(得分:1)
扩展以隐藏/显示单个元素
它不是100%相关的,但是如果您正在寻找一种简洁的方法来隐藏单个UIView
的元素(在堆栈视图或其他任何位置),则可以使用我做的这个简单扩展:
extension UIView {
func isHiddenAnimated(value: Bool, duration: Double = 0.2) {
UIView.animate(withDuration: duration) { [weak self] in self?.isHidden = value }
}
}
我用它来方便地用单行代码在堆栈视图中隐藏/显示带有动画的元素。示例:
validatableButton.isHiddenAnimated(value: false)
答案 4 :(得分:1)
希望这可以为其他人节省几个小时的挫败感。
动画隐藏和同时显示多个UIStackView子视图是一团糟。
在某些情况下,动画块中的.isHidden更改将正确显示,直到下一个动画为止,然后将忽略.isHidden。我为此找到的唯一可靠技巧是在动画块的完成部分重复.isHidden指令。
let time = 0.3
UIView.animate(withDuration: time, animations: {
//shows
self.googleSignInView.isHidden = false
self.googleSignInView.alpha = 1
self.registerView.isHidden = false
self.registerView.alpha = 1
//hides
self.usernameView.isHidden = true
self.usernameView.alpha = 0
self.passwordView.isHidden = true
self.passwordView.alpha = 0
self.stackView.layoutIfNeeded()
}) { (finished) in
self.googleSignInView.isHidden = false
self.registerView.isHidden = false
self.usernameView.isHidden = true
self.passwordView.isHidden = true
}
答案 5 :(得分:0)
我想分享这个功能,该功能非常适合在UIStackView
中隐藏和显示许多视图,因为我以前使用的所有代码都无法顺利运行,因为需要从某些图层中移除动画:
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)
}
}
}
答案 6 :(得分:-1)
只需添加这些代码行即可。
在Swift 4中:
UIView.animate(withDuration: 0.3){
viewInsideStackView.hidden = true //or false
}