web-dev-qa-db-fra.com

iOS - Animation de carte retournée

J'ai deux UIImageViews. L'un est le "Front" et l'autre le "Retour" ... Je tente de le mettre en œuvre de sorte que lorsque vous cliquez sur le "Retour", l'animation se déclenche et la carte est retournée.

L'animation fonctionne parfaitement. Mais cela anime la page entière, ce que je ne veux pas. Je veux seulement que la UIImageView retourne. Je ne vois pas ce que je fais mal. Probablement quelque chose d'évident.

@IBOutlet weak var answerImageViewer: UIImageView?
@IBOutlet weak var backAnswerImageViewer: UIImageView?

override func viewDidLoad() {
    super.viewDidLoad()
    startNewGame()
    retrieveNewQuestion()
    setupBannerMessage()
    customPlayButtons()

    let tapGesture = UITapGestureRecognizer(target: self, action: Selector("tap"))
    tapGesture.numberOfTapsRequired = 1
    backAnswerImageViewer?.addGestureRecognizer(tapGesture)
    backAnswerImageViewer?.userInteractionEnabled = true
}

var showingBack = true

func tap (){
    if showingBack{
       UIView.transitionFromView(self.backAnswerImageViewer!, toView: self.answerImageViewer!, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)

        backAnswerImageViewer?.hidden = true
        answerImageViewer?.hidden = false

        showingBack = false
    }
    else {
        showingBack = true

        UIView.transitionFromView(self.answerImageViewer!, toView: self.backAnswerImageViewer!, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)

        backAnswerImageViewer?.hidden = false
        answerImageViewer?.hidden = true
    }
}
9
Scott B

Votre problème est que vos UIImageViews sont directement sur la vue "page entière".

transitionFromView supprime le fromView de sa vue d'ensemble et ajoute le toView sur la vue d'ensemble avec l'animation donnée. Ainsi, il anime la superview. 

Vous devez inclure un UIView qui serveurs en tant que conteneur et avoir les deux imageViews en tant que sous-vues. Ajoutez votre geste sur la vue d'ensemble. De plus, vous ne devriez pas avoir de faibles références aux images imageViews, car une fois que vous avez terminé l’animation, votre référence à l’image imageView précédente disparaîtra. Il est probablement préférable d’ajouter ces éléments dans le code plutôt que dans le scénario. Pas besoin de cacher les imageViews.

Voici quelques exemples de code:

class MyViewController: UIViewController {

        @IBOutlet weak var containerView: UIView!

        private let backImageView: UIImageView! = UIImageView(image: UIImage(named: "back"))
        private let frontImageView: UIImageView! = UIImageView(image: UIImage(named: "front"))

        private var showingBack = false

        override func viewDidLoad() {
            super.viewDidLoad()

            frontImageView.contentMode = .ScaleAspectFit
            backImageView.contentMode = .ScaleAspectFit

            containerView.addSubview(frontImageView)
            frontImageView.translatesAutoresizingMaskIntoConstraints = false
            frontImageView.spanSuperview()

            let singleTap = UITapGestureRecognizer(target: self, action: #selector(flip))
            singleTap.numberOfTapsRequired = 1
            containerView.addGestureRecognizer(singleTap)
        }

        func flip() {   
            let toView = showingBack ? frontImageView : backImageView
            let fromView = showingBack ? backImageView : frontImageView
            UIView.transitionFromView(fromView, toView: toView, duration: 1, options: .TransitionFlipFromRight, completion: nil)
            toView.translatesAutoresizingMaskIntoConstraints = false
            toView.spanSuperview()
            showingBack = !showingBack
        }   

    }
12
Carien van Zyl

Si vous avez une button qui contient "carte" comme variable et que vous voulez changer son image en une nouvelle image appelée "1". Tout ce que vous avez à faire est ceci:

let image = UIImage(named: "1")
card.setImage(image, for: .normal)
UIView.transition(with: card, duration: 2, options: .transitionFlipFromRight, animations: nil, completion: nil)
9
J. Doe

Cette solution permet de retourner "une carte", en utilisant deux UIImageView (comme vous utilisez ...), je l’utilise dans un UICollectionView, ce qui n’est bien sûr pas nécessaire.

class CardCVCell: UICollectionViewCell {
    @IBOutlet weak var cardFrontImageView: UIImageView!
    @IBOutlet weak var cardBackImageView: UIImageView!

    private var flipped: Bool = false {
        didSet {
            cardFrontImageView.visible = flipped
            cardBackImageView.hidden = flipped
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        cardBackImageView.backgroundColor = UIColor.brownColor()
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        cardFrontImageView.image = nil
        flipped = false
    }

    func flipCard(cardModel: Card) {
        let flipped = cardModel.flipped
        let fromView = flipped ? cardFrontImageView : cardBackImageView
        let toView = flipped ? cardBackImageView : cardFrontImageView
        let flipDirection: UIViewAnimationOptions = flipped ? .TransitionFlipFromRight : .TransitionFlipFromLeft
        let options: UIViewAnimationOptions = [flipDirection, .ShowHideTransitionViews]
        UIView.transitionFromView(fromView, toView: toView, duration: 0.6, options: options) {
            finished in
            cardModel.flipped = !flipped
        }
    }
}

Le code provient de mon projet open source présentant le développement Swift, appelé SwiftIntro , qui est un jeu de mémoire, récupérant des images sur Instagram.

Veuillez noter que le modèle de carte doit être une classe et non un type de valeur

4
Sajjon

Vous devez avoir une vue de conteneur. Mettez answerImageViewer et backAnswerImageViewer en un seul UIView. Voici mon exemple de code.

    let frontView = UIView()
    let backView = UIView()

    let frame = CGRect(x: 40, y: 100, width: 300, height: 400)
    frontView.backgroundColor = .red
    backView.backgroundColor = .blue

    frontView.frame = CGRect(x: 0, y: 0, width: 300, height: 400)
    backView.frame = CGRect(x: 0, y: 0, width: 300, height: 400)

    let containerView = UIView()
    containerView.frame = frame

    containerView.addSubview(backView)
    containerView.addSubview(frontView)

    view.addSubview(containerView)
3
wint

Selon la réponse de Pankaj,

Dans iOS 12, l’utilisation de la méthode UIView.transition est un peu obsolète.

Sur l'appareil iOS 12, bien que j'ai mis à jour le code de Swift 4.0 à Swift 4.2, j'ai rencontré un problème de retournement de carte.

Vous pourriez mal comprendre cela parce que; En quelque sorte, Xcode ne suggère pas de changer cela. J'ai compris cela (grâce à Intellisense) en essayant de réécrire la méthode UIView.transition.

Avant: 

UIView.transition(with: cardView, duration: 1.0, options: transitionOptions, animations: {
        self.cardView.isHidden = true
        self.downButtonForBackCard.alpha = 1
    })

    UIView.transition(with: backCardView, duration: 1.0, options: transitionOptions, animations: {
        self.backCardView.isHidden = false
    })

Après:

 UIView.transition(with: cardView, duration: 1.0, options: transitionOptions, animations: {
        self.downButtonForBackCard.alpha = 1

    }) { (finish) in
        self.cardView.isHidden = true
    }

    UIView.transition(with: backCardView, duration: 1.0, options: transitionOptions, animations: {
        self.backCardView.isHidden = false
    }) { (finish) in

    }

PS: Ces deux codes sont tous de mon cas. Ne pas copier coller, juste prendre exemple.

J'espère pouvoir sauver la vie de quelqu'un. 

1
Oliver

Pour Swift 4

Il est préférable d’utiliser UIButton plutôt que UIImageView!

var isBackImageOpen = false

if isBackImageOpen {
isBackImageOpen = false
let image = UIImage(named: "backImage")
myBtn.setImage(image, for: .normal)
UIView.transition(with: myBtn, duration: 0.3, options: .transitionFlipFromLeft, animations: nil, completion: nil)

} else {

isBackImageOpen = true
let image = UIImage(named: "frontImage")
myBtn.setImage(image, for: .normal)
UIView.transition(with: myBtn, duration: 0.3, options: .transitionFlipFromRight, animations: nil, completion: nil)
}

J'espère que cette réponse aide :)!

1
Sree Ramana

Vous pouvez utiliser ce code 

UIView.transition (avec: self.yourViewName, durée: 0,5, options: [.transitionFlipFromRight], animations: nil, complétion: nil)

0
Pankaj Jangid

Essayez cette extension peut-être qu'il est facile à utiliser

extension UIView{

    func showFlip(){
            if self.isHidden{
                UIView.transition(with: self, duration: 1, options: [.transitionFlipFromRight,.allowUserInteraction], animations: nil, completion: nil)
                self.isHidden = false
            }

        }
    func hideFlip(){
        if !self.isHidden{
            UIView.transition(with: self, duration: 1, options: [.transitionFlipFromLeft,.allowUserInteraction], animations: nil,  completion: nil)
            self.isHidden = true
        }
    }
}

utiliser cette action de clic

func Flip(){
        if second_view.isHidden == true{
            second_view.showFlip()
            first_view.hideFlip()
        }else if first_view.isHidden == true{
            second_view.hideFlip()
            first_view.showFlip()
        }
}
0
gowtham