【问题标题】:iOS - Card flip animationiOS - 卡片翻转动画
【发布时间】: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

标签: ios swift animation uiimageview


【解决方案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)
            

            【讨论】:

              猜你喜欢
              • 2013-11-22
              • 2014-03-03
              • 1970-01-01
              • 1970-01-01
              • 2017-10-20
              • 1970-01-01
              • 1970-01-01
              • 2016-09-01
              相关资源
              最近更新 更多