代码之家  ›  专栏  ›  技术社区  ›  Infinity James

UIStackView隐藏视图动画

  •  106
  • Infinity James  · 技术社区  · 7 年前

    UIStackView

    iOS 10 animation

    iOS 11 animation

    两者的代码如下:

    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上以前的行为?

    6 回复  |  直到 7 年前
        1
  •  173
  •   LinusG.    7 年前

    修复正在添加 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中的一个问题,但公平地说,这一直是推荐的方法。

        2
  •  39
  •   jimpic    4 年前

    在被接受的答案的评论中已经提到了这一点,但这是我的问题,它不在这里的任何答案中,因此:

    从不 设置 isHidden = true

        3
  •  9
  •   ergunkocak    6 年前

    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
            )
        }
    }
    }
    
        4
  •  7
  •   Paul T.    6 年前

    我想分享这个功能,它很适合隐藏和显示中的许多视图 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)
            }
        }
    }
    
        5
  •  7
  •   Matjan    4 年前

    在某些情况下。在下一个动画之前,动画块中隐藏的更改将正确显示,然后。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
        }
    
        6
  •  1
  •   Hamid Reza Ansari    3 年前

    jimpic's answer

    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)
    })