Combining an animation of an UIImageView with a transition - ios

I am doing a transition of an UIImageView's image and would also like to move the image view at the same time. The results so far is that the image transitions, but not while moving.
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.transition(with: imageView, duration: 2.0, options: .transitionCrossDissolve, animations: {
self.imageView.image = UIImage(named: "otherImage")
}, completion: nil)
imageViewTopConstraint.constant = 200
UIView.animate(withDuration: 2.0) {
self.view.layoutIfNeeded()
}
}
}
Any ideas on how to solve this?

You can put your imageView inside a container, then animate the constraints of the container while doing the transition on the imageView.

Related

textField SlideAnimation when starting initial view controller

I need to create a right slide animation for TextField 1 and left slide animation for TextField2 . I tried to accomplish first right slide animation, but there is a problem. I have an slide animation, but there is another textfield under my animation textfield which doesn't move from it's constraints. I do not really understand why.
here is the code:
class ViewController: UIViewController {
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var PasswordField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
emailField.center.x = self.view.frame.width + 50
UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .allowAnimatedContent, animations: {
self.emailField.center.x = self.view.frame.width/2
self.view.layoutIfNeeded()
}, completion: nil)
}
}
Assuming your Storyboard looks similar to this:
Two text fields, with Top constraints, Width constraints equal to 80% of the view width, and CenterX constraints to the view's CenterX
Ctrl-Drag from each .centerX constraint to your view controller code to create #IBOutlet connections to the constraints:
#IBOutlet var emailCenterX: NSLayoutConstraint!
#IBOutlet var passwordCenterX: NSLayoutConstraint!
Your Storyboard will now look like this:
And you can move / animate the views by setting their .constant values at run-time:
class AViewController: UIViewController {
#IBOutlet var emailField: UITextField!
#IBOutlet var PasswordField: UITextField!
#IBOutlet var emailCenterX: NSLayoutConstraint!
#IBOutlet var passwordCenterX: NSLayoutConstraint!
var viewWidth: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
// move the textFields "off-screen"
emailCenterX.constant = UIScreen.main.bounds.width
passwordCenterX.constant = -UIScreen.main.bounds.width
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// reset the centerX constraints to the center of the view
emailCenterX.constant = 0
passwordCenterX.constant = 0
UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .allowAnimatedContent, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}

swift: show animation after returning in ViewController

I have first ViewController and second ViewController. When I return to first ViewController from second ViewController after that I want to show buttons in first ViewController.
To returning I use this code:
self.dismiss(animated: true, completion: nil)
And this code to show buttons in first ViewController
#IBOutlet weak var infoButton: UIButton!
#IBOutlet weak var nextButton: UIButton!
#IBOutlet weak var infoButtonTopConstraint: NSLayoutConstraint!
#IBOutlet weak var nextButtonBottomConstraint: NSLayoutConstraint!
#IBOutlet weak var infoButtonHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var nextButtonHeightConstraint: NSLayoutConstraint!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
showButtonAnimation()
//animaton()
}
func showButtonAnimation() {
self.infoButtonTopConstraint.constant += self.infoButtonHeightConstraint.constant
self.nextButtonBottomConstraint.constant -= self.nextButtonHeightConstraint.constant
UIView.animate(withDuration: 1.0, delay: 0.0,
options: [], animations: {
self.view.layoutIfNeeded()
})
}
But buttons not showing when I return from second ViewController.
Replace this
func showButtonAnimation() {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1.0, delay: 0.0,
options: [], animations: {
self.infoButtonTopConstraint.constant += self.infoButtonHeightConstraint.constant
self.nextButtonBottomConstraint.constant -= self.nextButtonHeightConstraint.constant
self.view.layoutIfNeeded()
})
}
EDIT 1
viewWillAppear not getting called reason : you are presenting 2nd viewController as overCurrentContext modalPresentationStyle.
Just replace overCurrentContext with fullScreen and it works.
Whenever you call viewWillAppear keep in mind that view where not loaded in main view so animation will not work proper. You should use a viewDidAppear.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showButtonAnimation()
}
And in your animation method update as below because you change constraint value inside animation block that in need to out of it.
func showButtonAnimation() {
self.infoButtonTopConstraint.constant += self.infoButtonHeightConstraint.constant
self.nextButtonBottomConstraint.constant -= self.nextButtonHeightConstraint.constant
UIView.animate(withDuration: 1.0, delay: 0.0,
options: [], animations: {
self.view.layoutIfNeeded()
})
}
I have tried your code and it is working for the first time, but the problem might be every time the constant value of the button constraint are increased.
so they might be hiding behind your main view.
Solution:- you can take flag and change its value when animation is completed.
Now when you come back from the second controller then you have to check in the viewWillAppear that if the buttons are visible or not, if they are visible then you do not have to call the showButtonAnimation method.
You can see where the buttons are in current screen with clicking on
button to see the UI hierarchy.
Hope this will solve your issue.
You can add a delegate in your second viewController. like:
protocol SecondViewControllerDelegate {
func vcDismissed()
}
Class SecondViewController : UIViewController {
weak var delegate: SecondViewControllerDelegate
.....
//Where you are dismissing your viewController, call the delegate method in completion.
func someMethod() {
self.dismiss(animated: true, completion: {
self.delegate.vcDismissed()
})
}
}
Now in your FirstViewController, conform the protocol and implement the method like below:
extension FirstViewController: SecondViewControllerDelegate {
func vcDismissed() {
//Here call your showButton method
self.showButton()
}
}
And do not forget to set the delegate when your are creating the instance of your secondViewController where you are presenting it. like
objSecondViewController.delegate = self
Hope this helps. for any query feel free to leave a comment.

Repeat animation from left to right smoothly

I'm trying to animate 3 squares from the left to the right. The squares should reappear from the left while they are disappearing from the right. The idea is that the squares represent clouds, so the idea is clear.
This is what I currently got:
class ViewController: UIViewController {
// contains the squares
#IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
startAnimating()
}
func startAnimating() {
UIView.animateKeyframes(withDuration: 10, delay: 0, options: .repeat, animations: {
self.containerView.center.x += self.view.bounds.width
}, completion: nil)
}
}
This is the result:
The squares move from the left to the right. This is good. The problem is that once the animation is done the squares just reappear from where they started. It isn't a smooth continuous movement where the clouds move from the left to the right and slowly reappear from the left again. How do you achieve this? Should there be a second containerView? Or remove the containerView and animate individual clouds?
The answer Milan Nosáľ solved the problem. A note though:
I placed containerView2 above containerView1 with the exact same
constraints (they overlap each other). Just make sure IB doesn't
include containerView2 as a subview of containerView1.
I guess the simplest approach for you know is to use two exactly the same containers. You can use exactly the same code, and put the containerView2 above containerView to make sure that cover one another.
And then simply use:
class ViewController: UIViewController {
// contains the squares
#IBOutlet weak var containerView: UIView!
#IBOutlet weak var containerView2: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// this will transform the containerView2 to the left to appear as if it was exactly to the left of the containerView
containerView2.transform = CGAffineTransform.identity.translatedBy(x: -self.view.bounds.width, y: 0)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
startAnimating()
}
func startAnimating() {
UIView.animateKeyframes(withDuration: 10, delay: 0, options: .repeat, animations: {
self.containerView.center.x += self.view.bounds.width
self.containerView2.center.x += self.view.bounds.width
}, completion: nil)
}
}
The containerView2 will represent the clouds coming back from the left.
You could try something like putting containerView.center.x -= 200 right before starting the animation. This way it first appears from the left side.

Weird Button Animation

It's my first try on IOS animation, so if I'm worry from the very beginning, just tell me the right direction.
All I want: when I click ButtonOne, Label disappears slowly.
The code as below:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var labelHeight: NSLayoutConstraint!
private var isHidden: Bool = false
#IBAction func clickButtonOne(sender: UIButton) {
isHidden = !isHidden
if isHidden {
labelHeight.constant = 0
} else {
labelHeight.constant = 60
}
UIView.animateWithDuration(1.0, animations: {
() -> Void in
self.view.layoutIfNeeded()
}, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Before I click ButtonOne:
After I click ButtonOne(label shrinks from bottom to top):
The UILabel is disappearing, but it's content is still visible.
You need to set the clipsToBounds property of the UILabel to true.
label.clipsToBounds = true
You can set the same property in the interface builder by checking the Clip Subviews property in the attributes inspector.
I think you should also animate UIView.alpha property:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton!
#IBOutlet weak var labelHeight: NSLayoutConstraint!
private var isHidden: Bool = false
#IBAction func clickButtonOne(sender: UIButton) {
isHidden = !isHidden
var alpha: CGFloat = 1
if isHidden {
alpha = 0
labelHeight.constant = 0
} else {
labelHeight.constant = 60
}
UIView.animateWithDuration(1.0, animations: {
() -> Void in
self.button.alpha = alpha
self.view.layoutIfNeeded()
}, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}

views constrained to banner view jump suddenly instead of slowly animating

I am trying to animate banner view from the bottom to the screen using constraints. the button is attached to the bannerview and it should always be at the same distance from banner. This is what I get: https://vid.me/F008
As you can see the button jumps suddenly, but I wanted it to move slowly with UIView.animateWithDuration method. This is my code
#IBOutlet weak var bannerToBottomGuideConstraint: NSLayoutConstraint!
#IBOutlet weak var buttonToBannerConstraint: NSLayoutConstraint!
#IBOutlet weak var bannerView: ADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
self.canDisplayBannerAds = true
bannerToBottomGuideConstraint.constant -= CGRectGetHeight(bannerView.bounds)
bannerView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0)
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
let time = 0.6
if banner.bannerLoaded == false{
self.view.layoutIfNeeded()
bannerToBottomGuideConstraint.constant += CGRectGetHeight(bannerView.bounds)
UIView.animateWithDuration(time, animations: {
self.view.layoutIfNeeded()
}, completion: {_ in
})
}
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
if bannerView.bannerLoaded{
bannerToBottomGuideConstraint.constant -= CGRectGetHeight(bannerView.bounds)
UIView.animateWithDuration(0, animations: {
self.view.layoutIfNeeded()
}, completion: {_ in
})
}
}
Instead of self.view.layoutIfNeeded() in the animation block, call banner.superview!.layoutIfNeeded().

Resources