UIStackView 隐藏视图动画
UIStackView Hide View Animation
在 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 上恢复以前的行为?
刚遇到同样的问题。
修复是在动画块中添加 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)
不确定为什么这突然成为 iOS11 中的一个问题,但公平地说,这一直是推荐的方法。
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
)
}
}
}
我想在 UIStackView
中分享这个非常适合隐藏和显示许多视图的函数,因为我之前使用的所有代码都无法正常工作,因为需要从某些图层中删除动画:
extension UIStackView {
public func make(viewsHidden: [UIView], viewsVisible: [UIView], animated: Bool) {
let viewsHidden = viewsHidden.filter({ [=10=].superview === self })
let viewsVisible = viewsVisible.filter({ [=10=].superview === self })
let blockToSetVisibility: ([UIView], _ hidden: Bool) -> Void = { views, hidden in
views.forEach({ [=10=].isHidden = hidden })
}
// need for smooth animation
let blockToSetAlphaForSubviewsOf: ([UIView], _ alpha: CGFloat) -> Void = { views, alpha in
views.forEach({ view in
view.subviews.forEach({ [=10=].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)
}
}
}
希望这可以为其他人节省几个小时的挫败感。
动画同时隐藏和显示多个 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
}
它已经在已接受答案的评论中提到,但这是我的问题并且不在此处的任何答案中所以:
确保永远不会在已经隐藏的视图上设置isHidden = true
。这会弄乱堆栈视图。
根据,我写了一个简单的函数,解决了我在stackView中用动画显示和隐藏视图的问题。
func hide(_ vu: UIView) {
if vu.isHidden == true {
return
} else {
vu.isHidden = true
}
}
func show(_ vu: UIView) {
if vu.isHidden == true {
vu.isHidden = false
} else {
return
}
}
使用上面的函数:
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: {
self.hide(self.nameTextField)
})
在 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 上恢复以前的行为?
刚遇到同样的问题。
修复是在动画块中添加 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)
不确定为什么这突然成为 iOS11 中的一个问题,但公平地说,这一直是推荐的方法。
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
)
}
}
}
我想在 UIStackView
中分享这个非常适合隐藏和显示许多视图的函数,因为我之前使用的所有代码都无法正常工作,因为需要从某些图层中删除动画:
extension UIStackView {
public func make(viewsHidden: [UIView], viewsVisible: [UIView], animated: Bool) {
let viewsHidden = viewsHidden.filter({ [=10=].superview === self })
let viewsVisible = viewsVisible.filter({ [=10=].superview === self })
let blockToSetVisibility: ([UIView], _ hidden: Bool) -> Void = { views, hidden in
views.forEach({ [=10=].isHidden = hidden })
}
// need for smooth animation
let blockToSetAlphaForSubviewsOf: ([UIView], _ alpha: CGFloat) -> Void = { views, alpha in
views.forEach({ view in
view.subviews.forEach({ [=10=].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)
}
}
}
希望这可以为其他人节省几个小时的挫败感。
动画同时隐藏和显示多个 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
}
它已经在已接受答案的评论中提到,但这是我的问题并且不在此处的任何答案中所以:
确保永远不会在已经隐藏的视图上设置isHidden = true
。这会弄乱堆栈视图。
根据
func hide(_ vu: UIView) {
if vu.isHidden == true {
return
} else {
vu.isHidden = true
}
}
func show(_ vu: UIView) {
if vu.isHidden == true {
vu.isHidden = false
} else {
return
}
}
使用上面的函数:
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: {
self.hide(self.nameTextField)
})