iOS - 卡片翻转动画

Posted

技术标签:

【中文标题】iOS - 卡片翻转动画【英文标题】:iOS - Card flip animation 【发布时间】:2016-09-15 19:40:46 【问题描述】:

我有两个 UIImageViews。一个是“前”,一个是“后”。 我正在尝试实现它,以便当您单击“返回”时,它会触发动画并翻转卡片。

动画效果很好。但它使整页动画,这是我不想要的。我只希望UIImageView 翻转。我看不出我做错了什么。可能是显而易见的。

@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
    

【问题讨论】:

整页动画是什么意思?可以提供截图吗? 不只是 UIImageView 翻转,而是 View Controller 翻转 你应该使用UIView.AnimationOptions showHideTransitionViews 【参考方案1】:

如果您有一个将“card”作为变量的button,并且您想将他的图像更改为一个名为“1”的新图像。您所要做的就是:

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

【讨论】:

这样一个简单的解决方案。我在即将推出的抽认卡应用中实现了它。我添加了一个布尔值以在翻转之间进行更改。 “如果 isFlipped UIView.transition(with: flashcardView, duration: 0.5, options: .transitionFlipFromRight, animations: nil, completion: nil) isFlipped = false else UIView.transition(with: flashcardView, duration: 0.5, options: . transitionFlipFromLeft, 动画: nil, 完成: nil) isFlipped = true " 当我尝试这段代码时,图像仅在翻转后设置,而不是在翻转时设置...【参考方案2】:

您的问题是您的 UIImageViews 直接在“整页”视图上。

transitionFromView 从其父视图中移除 fromView 并在具有给定动画的父视图上添加 toView。因此,它为超级视图设置了动画。

您应该包含一个作为容器服务的 UIView,并将两个 imageViews 作为子视图。在容器视图上添加您的点击手势。此外,你不应该对 imageViews 有弱引用,因为一旦你完成了一次动画,你对后面的 imageView 的引用就会消失。将这些添加到代码中可能比故事板更好。无需隐藏 imageViews。

下面是一些示例代码:

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
           

    

【讨论】:

【参考方案3】:

这个解决方案是用于翻转“一张卡片”,使用两个UIImageView(就像你正在使用...),我在 UICollectionView 中使用它,那当然不是必须的。

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
        
    

代码取自我的open source project introducing people to Swift development, called SwiftIntro,这是一个记忆游戏,从 Instagram 获取图像。

请注意模型 Card 必须是类而不是值类型

【讨论】:

我的整个 UIView 正在旋转而不是 UIImageview :( @ray-king 你是在 UIImageViews 中传递给transitionFromView:toView:duration 吗? 是的,但我想通了,这是错误的子视图结构 整个 viewController 正在翻转,即使我只将我的 uiview 设置为 transitionFromView:toView:duration。想法? @david-seek 您确定您没有在您的UIViewController 上意外地将toViewfromView 设置为view (self.view)? :S【参考方案4】:

您需要有一个容器视图。将answerImageViewerbackAnswerImageViewer 放入一个UIView。这是我的示例代码。

    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)

【讨论】:

【参考方案5】:

根据Pankaj的回答,

ios 12 中,UIView.transition 方法的使用有点被弃用了。

在 iOS 12 设备中,虽然我已经将代码从 Swift 4.0 更新到 Swift 4.2,但我遇到了翻牌问题。

您可能会错过这个,因为;不知何故,Xcode 不建议改变这一点。当我尝试重写 UIView.transition 方法时,我意识到了这一点(感谢 Intellisense)。

之前:

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
    )

之后:

 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:这两个代码都来自我的案例。请勿复制粘贴,仅举个例子。

我希望我能拯救别人的生命。

【讨论】:

【参考方案6】:

对于 Swift 4

最好使用 UIButton 而不是 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)

希望这个答案有帮助:)!

【讨论】:

【参考方案7】:

您可以使用此代码

UIView.transition(with: self.yourViewName, duration: 0.5, options: [.transitionFlipFromRight], animations: nil, completion: nil)

【讨论】:

不要复制粘贴答案【参考方案8】:

试试这个扩展可能很容易使用

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
        
    

在点击操作中使用它

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

【讨论】:

【参考方案9】:

之前的答案很好,但添加了“showHideTransitionViews”作为选项,它允许您不必手动隐藏并显示动画视图。请记住,这两个视图需要在另一个视图中。此过渡将旋转超级视图。

  UIView.transition(from: view1, to: view2, duration: 0.5, options: [.transitionFlipFromLeft, .showHideTransitionViews], completion: nil)

【讨论】:

以上是关于iOS - 卡片翻转动画的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 仅针对特定视图翻转动画

卡片翻转动画 Internet Explorer 11

Material-ui卡片翻转动画

如何在 UIScrollView 中的对象(UIViews)上执行翻转动画

vue组件reload之后不会执行动画

在RecyclerView中翻转CardView