web-dev-qa-db-fra.com

UIStackView Masquer l'animation

Dans iOS 11, le comportement de l’animation de masquage dans un UIStackView a changé, mais j’ai été incapable de trouver cette documentation documentée.

iOS 10

iOS 10 animation

iOS 11

iOS 11 animation

Le code dans les deux est le suivant:

UIView.animate(withDuration: DiscoverHeaderView.animationDuration,
                       delay: 0.0,
                       usingSpringWithDamping: 0.9,
                       initialSpringVelocity: 1,
                       options: [],
                       animations: {
                            clear.isHidden = hideClear
                            useMyLocation.isHidden = hideLocation
                        },
                       completion: nil)

Comment restaurer le comportement précédent sur iOS 11?

48
Infinity James

Je viens d'avoir le même problème. Le correctif consiste à ajouter stackView.layoutIfNeeded() à l'intérieur du bloc d'animation. Où stackView est le conteneur des éléments que vous souhaitez masquer.

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)

Vous ne savez pas pourquoi c'est soudainement un problème dans iOS 11 mais, pour être juste, cela a toujours été l'approche recommandée.

86
Springham

Swift 4 Extension:

// 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
        )
    }
}
}
3
ergunkocak

Je souhaite partager cette fonction qui permet de masquer et d'afficher de nombreuses vues dans UIStackView, car avec tout le code que j'ai utilisé auparavant ne fonctionnait pas correctement car il fallait supprimer l'Animation de certains calques:

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)
        }
    }
}
0
Paul T.