Search code examples
iosswiftuiviewflipuiviewanimationtransition

UIViewAnimationTransition flip UIImageView


Video

My UIView.transitions in my tapped function at the bottom works the first time but the second time for my else statement to flip back to the front side crashes every time. Getting error message "fatal error: unexpectedly found nil while unwrapping an Optional value". Want to successfully flip front to back and back to front every time :) thanks you in advance pals. ;) Also, I added my ImageOne & ImageTwo views in my storyboard!

import UIKit
import Foundation
import Firebase
import FirebaseDatabase

class ViewController: UIViewController {

@IBOutlet weak var mainScrollView: UIScrollView!
@IBOutlet weak var imageOne: UIImageView!
@IBOutlet weak var imageTwo: UIImageView!

var myImageArray = [UIImage]()
var myImageArray2 = [UIImage]()

var back: UIImageView!
var front: UIImageView!

var showingFront = true

override func viewDidLoad() {
    super.viewDidLoad()
    SignedIn()

    self.view.addGestureRecognizer(revealViewController().panGestureRecognizer())

    let singleTap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapped))
    singleTap.numberOfTapsRequired = 1
    mainScrollView.addGestureRecognizer(singleTap)
    mainScrollView.isUserInteractionEnabled = true

    mainScrollView.frame = view.frame

    myImageArray = [image1, image2 ,image3, image4, image5]
    myImageArray2 = [imageText1, imageText2 ,imageText3, imageText4, imageText5]

    for i in 0..<myImageArray.count {

        front = UIImageView()
        front.image = myImageArray[i]
        front.contentMode = .scaleToFill
        let yPosition = self.view.frame.height * CGFloat(i) + self.view.frame.height/2 - (self.view.frame.height / 1.1)/2
        let xPosition = self.view.frame.width/2 - (self.view.frame.width / 1.1)/2
        front.frame = CGRect(x: xPosition, y: yPosition, width: self.view.frame.width / 1.1, height: self.view.frame.height / 1.1)
        front.layer.borderWidth = 5

        back = UIImageView()
        back.image = myImageArray2[i]
        back.contentMode = .scaleToFill
        back.frame = CGRect(x: xPosition, y: yPosition, width: self.view.frame.width / 1.1, height: self.view.frame.height / 1.1)
        back.layer.borderWidth = 5

        mainScrollView.contentSize.height = mainScrollView.frame.height * CGFloat(i + 1)

        imageOne.addSubview(front)
        imageTwo.addSubview(back)
    }
}

func tapped() {
    print("Hello")
    if (showingFront) {
        UIView.transition(from: imageOne, to: imageTwo, duration: 1, options: UIViewAnimationOptions.transitionFlipFromRight, completion: nil)
        showingFront = false
    } else {
        UIView.transition(from: imageTwo, to: imageOne, duration: 1, options: UIViewAnimationOptions.transitionFlipFromLeft, completion: nil)
        showingFront = true
    }
}

}


Solution

  • You need to add a second animation option to keep the "from" view in play. Here's how I do it:

    // declare the animation options
    let transitionOptions: UIViewAnimationOptions = [.transitionFlipFromRight, .showHideTransitionViews]
    
    func tapped() {
        print("Hello")
        if (showingFront) {
            UIView.transition(from: imageOne, to: imageTwo, duration: 1, options: transitionOptions, completion: nil)
            showingFront = false
        } else {
            UIView.transition(from: imageTwo, to: imageOne, duration: 1, options: transitionOptions, completion: nil)
            showingFront = true
        }
    }
    

    I recall that it took me a solid hour to add a second option, as Swift 2 code you could do it differently.