CenterX Constraint animation issue - ios

I am trying to implement following animation for my application onboarding and it needs to be play forever and reverse back every time it finishes.
I designed following image to accomplish that animation.
The image size is 880x335. So I wrote following code to animate the image.
func startAnimation(with duration: TimeInterval, afterDelay time: TimeInterval, horizontalConstantFirstPosition: CGFloat, horizontalConstantSecondPosition: CGFloat) {
switch animationOrder {
case .first:
self.animatedImageViewAnimatableConstraint.constant = 110
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .second
})
case .second:
self.animatedImageViewAnimatableConstraint.constant = -110
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .third
})
case .third:
self.animatedImageViewAnimatableConstraint.constant = -330
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .fourth
})
case .fourth:
self.animatedImageViewAnimatableConstraint.constant = 110
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .second
})
}
}
Basically, animatedImageViewAnimatableConstraint is the center X constraint that is initialized with 330 which is the position of first image I designed. Every time my animation method is called I changed center x anchor to the positions of value 330, 110, -110, -330 and so on.
However, when I applied it is not animating as expected. It returns back from fourth portion of the image to first one, it is excepted to go from fourth position to second one as shown above.
What should I do for the correct one, or which part is looking like wrong? Thanks in advance.

#IBOutlet weak var imageView: UIImageView!
let images = [#imageLiteral(resourceName: "img1"), #imageLiteral(resourceName: "img2"), #imageLiteral(resourceName: "img3")]
imageView.animationImages = images
imageView.animationDuration = 3.0 //1 sec for each image
imageView.animationRepeatCount = 0 //Set 0 for infinite
imageView.startAnimating()
To stop just call
imageView.stopAnimating()

Related

iOS simulator ghost image edge left over on the screen after animation

I added spring option to an UIImage. It worked fine on my phone, very nice. Bouncy and smooth.
But when I run it on the iOS simulators, it always leaves some edges on the screen.
It becomes a problem when I need to upload screenshots to App Store.
This is my code:
let theTile = numberTile
let bounds = theTile.bounds
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: [.curveEaseInOut, .allowUserInteraction], animations: {
theTile.bounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width * 1.2, height: bounds.size.height * 1.2)
}, completion: nil)
This is the shrink back code
let theTile = numberTile
let bounds = theTile.bounds
UIView.animate(withDuration: 0.3, delay: 0, options: .allowUserInteraction, animations: {
theTile.bounds = CGRect(origin: bounds.origin, size: self.size)
}, completion: nil)
Try this although this might not be your only issue. If that is a collection view I would need to see your cell for row function as you may be loading a cell with the bounds messed up to start with. Here is a suggestion though. Animate the transform instead.
//to animate larger
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.2,initialSpringVelocity: 10, options: [.curveEaseInOut, .allowUserInteraction], animations: {
theTile.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
}, completion: nil)
//animate smaller
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: [.curveEaseInOut, .allowUserInteraction], animations: {
theTile.transform = .identity
}, completion: nil)
If this is a collection view in cell for row you may need to check for selected index but def if not selected you need to set the transform to identity.
EDIT:
You say this does not fix the issue. What environment are you running? Type of Mac. I personally believe it is a code issue somewhere else as I have written tons of animation code and never seen this bug. Here is a minimum example that does not create "ghost layers" on my device or simulator. If you can make a minimal example that does it would help a lot... Until then I think it is something in your code possibly your collection view.
import UIKit
class ViewController: UIViewController {
lazy var box : UIView = {
let v = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
v.backgroundColor = .blue
v.center = self.view.center
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .lightGray
self.view.addSubview(box)
box.layer.cornerRadius = 8
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
fireEvent()
super.touchesBegan(touches, with: event)
}
func fireEvent(){
if box.transform == .identity{
//to animate larger
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.2,initialSpringVelocity: 10, options: [.curveEaseInOut, .allowUserInteraction], animations: {
self.box.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
}, completion: nil)
}else{
//animate smaller
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: [.curveEaseInOut, .allowUserInteraction], animations: {
self.box.transform = .identity
}, completion: nil)
}
}
}

iOS Animation is not working after switch to another VC Swift

I have small background animation to change gradient, ex u can see here animation
As you see if i open app first time, animation is working, after the changing View Controller animation is stop.
My code:
func animateGrandient() {
UIView.animate(withDuration: 15, delay: 0, options: [.autoreverse, .curveLinear, .repeat], animations: {
let x = -(self.gradientView.frame.width - self.view.frame.width)
self.gradientView.transform = CGAffineTransform(translationX: x, y: 0)
})
}
And outlet:
#IBOutlet weak var gradientView: UIImageView!
This happens because your self.gradientView.transform is changed already before your animation is executed, so you need to reset your self.gradientView.transform
Add this line self.gradientView.transform = CGAffineTransform.identity in the beginning of that method
fixed code
func animateGrandient() {
self.gradientView.transform = CGAffineTransform.identity
UIView.animate(withDuration: 15, delay: 0, options: [.autoreverse, .curveLinear, .repeat], animations: {
let x = -(self.gradientView.frame.width - self.view.frame.width)
self.gradientView.transform = CGAffineTransform(translationX: x, y: 0)
})
}

pop out animation of UIView in swift

I am learning swift, I was successfully able to do popup animation of an UIView as below code but now i want to do reverse of it. i.e the way the UIView was animated should go back on a button click, Like the view is shrinking and then disappears.
popupView.isHidden = false
popupInnerView.isHidden = false
popupInnerView.transform = CGAffineTransform(scaleX: 0, y: 0)
UIView.animate(withDuration: 1, delay: 0, options: .curveLinear, animations: {
self.popupView.alpha = 1.0;
self.popupInnerView.transform = .identity
}, completion: nil)
Check if this one works for you. I have bound the showing and hiding of popup to buttons but you can bind them to anything.
For this to work
Drag and drop a uiview(your popup) into dock of view controller (see picture)
Make outlet of your uiview(popup) in your view controller. I am calling it popupView
For showing popup with Animation use the code
#IBAction func btnShowPopupTapped(_ sender: UIButton) {
popupView.center = view.center
popupView.alpha = 1
popupView.transform = CGAffineTransform(scaleX: 0.8, y: 1.2)
self.view.addSubview(popupView)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0, options: [], animations: {
//use if you want to darken the background
//self.viewDim.alpha = 0.8
//go back to original form
self.popupView.transform = .identity
})
}
And for hiding the popup
#IBAction func btnHideMeTapped(_ sender: Any) {
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0, options: [], animations: {
//use if you wish to darken the background
//self.viewDim.alpha = 0
self.popupView.transform = CGAffineTransform(scaleX: 0.2, y: 0.2)
}) { (success) in
self.popupView.removeFromSuperview()
}
}
Note: If you want to darken the background as in gif.
Drag and drop a uiview into your view heirarchy (view dim). see the pic
pin to 0, 0 , 0 ,0 to the main view
set its background color to black
set is alpha to 0
uncomment the line (self.viewDim.alpha = 0.8) in "btnShowPopupTapped" Action
uncomment the line (self.viewDim.alpha = 0) in "btnHideMeTapped" Action
Let me know if this helps.
Try This
For Zoom in
UIView.animate(withDuration: 1, delay: 0, options: .curveLinear, animations: {
self.popupInnerView.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
}, completion: { _ in
self.popupInnerView.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
})
For Zoom Out
UIView.animate(withDuration: 1, delay: 0, options: .curveLinear, animations: {
self.popupInnerView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
}, completion: nil)
This code worked for Pop Out
UIView.animate(withDuration: 1, delay: 0, options: .curveLinear, animations: {
self.popupView.alpha = 0.0;
self.popupInnerView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
}, completion: { _ in
self.popupView.isHidden = true
self.popupInnerView.isHidden = true
})

How to have a role in animation of table view cells

How can I create an animation like in the following link?
Link
I'm using the below for animate cell from left in tableview delegate method willdisplaycell. Issue is all the cells are animating at a time not one after other, can anyone advice me how can I achieve that?
let direction:CGFloat = -1.0
cell?.layer.opacity = 0.4
cell?.transform = CGAffineTransform(translationX: (cell?.bounds.size.width)! * direction, y: 0)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.85, initialSpringVelocity: 0.8, options: [], animations: {
cell?.transform = CGAffineTransform.identity
cell?.contentView.layer.opacity = 1.0
}) { _ in
self.isForExpand = false
}

Swift: Load .Xib with animation

Currently I am loading a new .Xib of class CreateAnAccount: UIView form a button pressed on another view.
At the moment it immediately switches to the Xib which is great, but is there a way of animating this? below is the code in the button.
#IBAction func createAnAccount(sender: AnyObject) {
let createAnAccountView = NSBundle.mainBundle().loadNibNamed("CreateAnAccount", owner: self, options: nil)[0] as! CreateAnAccount
createAnAccountView.frame = CGRectMake(0, 0, UIScreen.mainScreen().applicationFrame.size.width, UIScreen.mainScreen().applicationFrame.size.height + 20)
createAnAccountView.loginHandler = loginHandler
self.addSubview(createAnAccountView)
println("Create An Account Pressed")
}
Swift 4. Just place your animation code into layoutSubviews func. Works perfect for me.
override func layoutSubviews() {
super.layoutSubviews()
animate()
}
func animate() {
self.transform = CGAffineTransform(scaleX: 0.3, y: 2)
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0, options: [.allowUserInteraction, .curveEaseOut], animations: {
self.transform = .identity
})
self.alpha = 1
}
Swift 5. #coldembrace answer
func animate() {
self.view.transform = CGAffineTransform(scaleX: 0.3, y: 2)
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0, options: [.allowUserInteraction, .curveEaseOut], animations: {
self.view.transform = .identity
})
self.view.alpha = 1
}
You can try like this
UIView.transitionWithView(self.view, duration: 0.5, options:UIViewAnimationOptions.CurveEaseInOut,animations: {self.view.addSubview(createAnAccountView)}, completion: nil)
Moreover you change the UIViewAnimationOptions to have a desired effect.

Resources