0

I'm attempting to smoothly transition between two images by using a UIImageView and by animating the transition, but it seems that the transition isn't working as expected as a white screen appears instead of the new image fading in.

I've used https://stackoverflow.com/a/42710002/7908770 for reference and can't figure out where I've gone wrong :(

class ViewController: UIViewController {

    var bckgImageView = UIImageView(image: UIImage(named: "one"))

    override func viewDidLoad() {
        super.viewDidLoad()

        bckgImageView.frame = self.view.frame
        self.view.addSubview(bckgImageView)

        animateBackground()

    }

    func animateBackground() {

        UIView.transition(with: self.view,
                          duration: 5,
                          options: .transitionCrossDissolve,
                          animations: { self.bckgImageView.image = UIImage(named: "two") },
                          completion: nil)

    }
Adi219
  • 4,712
  • 2
  • 20
  • 43
  • Does `self.view` has correct size? You can move this code into `viewDidAppear` for testing. – Mike H Jul 09 '19 at 13:16

2 Answers2

1

AutoLayout not calculated yet when in viewDidLoad

You can set frame when layout changed in viewDidLayoutSubviews. Try this

class ViewController: UIViewController {

    var bckgImageView = UIImageView(image: UIImage(named: "one"))

    override func viewDidLoad() {
        super.viewDidLoad()

        bckgImageView.frame = self.view.frame
        self.view.addSubview(bckgImageView)

        animateBackground()

    }

    func animateBackground() {

        UIView.transition(with: self.view,
                          duration: 5,
                          options: .transitionCrossDissolve,
                          animations: { self.bckgImageView.image = UIImage(named: "two") },
                          completion: nil)

    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        bckgImageView.frame = self.view.frame
    }

}
Vicaren
  • 654
  • 4
  • 12
  • This works to an extent :( , the second image is appearing, but there's no animation and the initial image is never shown – Adi219 Jul 09 '19 at 14:08
  • Check your constraints and put the animate didAppear. And be sure your outlets and image is in your bundle – Vicaren Jul 09 '19 at 16:34
0

First, you're setting the frame of the image view to the frame of the "root" view, which is not-yet defined in viewDidLoad(). You're much better off using constraints and letting auto-layout size the view.

Second, if you are starting your animation in viewDidLoad() or even in viewDidLayoutSubviews(), the screen is not yet visible --- so you don't see the initial image (or you only see it very briefly, if the animation is short).

So, start your animation at viewDidAppear(), or, give it a little delay, as in the following:

class ViewController: UIViewController {

    var bckgImageView = UIImageView(image: UIImage(named: "one"))

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(bckgImageView)
        bckgImageView.translatesAutoresizingMaskIntoConstraints = false

        // constrain image view to all 4 sides
        NSLayoutConstraint.activate([
            bckgImageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            bckgImageView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            bckgImageView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            bckgImageView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            ])

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // start animation after 1 second
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
            self.animateBackground()
            })

    }

    func animateBackground() {

        UIView.transition(with: self.view,
                          duration: 5,
                          options: .transitionCrossDissolve,
                          animations: { self.bckgImageView.image = UIImage(named: "two") },
                          completion: nil)

    }
}
DonMag
  • 69,424
  • 5
  • 50
  • 86