I'm trying to implement this animation where a UIButton fades out when a user saves a file. While the button fades out, a UIImageView of a check mark image fades in place of the button. Once the imageview has fully faded in, then it fades out and the button fades back in.
UIView.animateWithDuration(0.60, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.recButton.alpha = 0.0
}, completion: {
(value: Bool) in
UIView.animateWithDuration(0.60, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.checkView.alpha = 1.0
}, completion: {
(value: Bool) in
UIView.animateWithDuration(0.60, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.checkView.alpha = 0.0
}, completion: {
(value: Bool) in
UIView.animateWithDuration(0.60, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.recButton.alpha = 1.0
self.recButton.enabled = true
}, completion: nil)
})
})
})
While the method above does work, its not as smooth as I would like. Is there a better way to go about this?
You need four keyframes for the animation you want: button fade out, image fade in, image fade out, button fade in.
let button: UIButton
let checkmarkImage: UIImageView
button.alpha = 1.0
checkmarkImage = 0.0
UIView.animateKeyframesWithDuration(2.4, delay: 0, options: .CalculationModeLinear, animations: {
UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.25, animations: {
button.alpha = 0.0
})
UIView.addKeyframeWithRelativeStartTime(0.25, relativeDuration: 0.25, animations: {
checkmarkImage.alpha = 1.0
})
UIView.addKeyframeWithRelativeStartTime(0.5, relativeDuration: 0.25, animations: {
checkmarkImage.alpha = 0.0
})
UIView.addKeyframeWithRelativeStartTime(0.75, relativeDuration: 0.25, animations: {
button.alpha = 1.0
})
}, completion: nil)
This question raised my curiosity - this keyframe thing is pretty cool.
Related
I'm trying to build an iOS app with a neon light that flickers randomly and constantly like a real one would.
I'm not totally sure how to get the animation to repeat constantly, and I'm not sure how to get it to just run automatically and forever. I put this in the viewDidLoad, but I'm not sure if that's really the best place to put it?
UIImageView.animate(withDuration: 0.05, delay: 5.0, options: .repeat, animations: {
UIImageView.animate(withDuration: 0.05, delay: 2.0, animations: {
self.Aletter.alpha = 0.2
}) { (_) in
UIImageView.animate(withDuration: 0.05, delay: 0.0, animations: {
self.Aletter.alpha = 1.0
}, completion: { (_) in
UIImageView.animate(withDuration: 0.05, delay: 2.0, animations: {
self.Aletter.alpha = 0.6
}, completion: { (_) in
UIImageView.animate(withDuration: 0.05, delay: 0.0, animations: {
self.Aletter.alpha = 1.0
}, completion: { (_) in
UIImageView.animate(withDuration: 0.05, delay: 0.0, animations: {
self.Aletter.alpha = 0.6
}, completion: { (_) in
UIImageView.animate(withDuration: 0.05, delay: 0.0, animations: {
self.Aletter.alpha = 1.0
}, completion: { (_) in
UIImageView.animate(withDuration: 0.05, delay: 0.0, animations: {
self.Aletter.alpha = 0.6
}, completion: { (_) in
UIImageView.animate(withDuration: 0.05, delay: 0.0, animations: {
self.Aletter.alpha = 1.0
}, completion: { (_) in
})
})
})
})
})
})
})
}
})
This code will run my series of flickers, but only once. I need it to go continuously.
As suggested by Matt in the comments section, you can use something like this:
private func flicker() { [weak self] in
UIView.animate(withDuration: 0.05, animations: {
self?.Aletter.alpha = CGFloat.random(in: 0.1...1.0)
}) { _ in
// When this round of animations completes call the same method again to start the animations again with a new random value for alpha.
self?.flicker()
}
}
And just call flicker() in your viewDidLoad(). flicker method starts an animation with a random alpha value for Aletter view, and when this animation completes it calls itself again.
As a side note, use small first letters for your variables, Aletter should be aletter or maybe aLetter based on the context.
In a navigation controller embedded project, using animations, I cannot avoid getting a "fast preview" of the buttons present in the next ViewController, where those buttons will slide from left border of the screen to the center.
So, when I tap in first VC, see for an instant the buttons in second VC, and then the second VC appears and the animation works (and it works fine)
In home controller the button is:
#objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
print("tapped")
//animate 1/2
UIView.animate(withDuration: 0.8, animations: { () -> Void in
self.mainButtonContainerView.center.y -= self.view.bounds.width //self.view.frame.origin
self.mainButtonContainerView.isUserInteractionEnabled = false
self.mainButtonContainerView.alpha = 0.0
})
//animate2/2
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1) ) {
self.pushShowNextVC_ChoiceVC(dataToPass: "")
}
}
Then, the animation in second VC ViewDidLoad is:
for singleView in coantinersOutCollection {
//animation
singleView.center.x -= self.view.bounds.width
singleView.layer.cornerRadius = singleView.bounds.size.height/2
singleView.backgroundColor = UIColor.white
singleView.layer.borderColor = Constants.skyBlue3Color.cgColor
singleView.layer.borderWidth = 1
}
for singleLabel in labesForButtons {
singleLabel.textColor = Constants.skyBlue3Color
singleLabel.font = UIFont.boldSystemFont(ofSize: 17.0)
}
for singleImage in self.iconButtonImages {
// singleImage.image = UIImage(named: "")
singleImage.backgroundColor = UIColor.clear
singleImage.layer.borderWidth = 1
singleImage.layer.borderColor = Constants.skyBlue3Color.cgColor
}
UIView.animate(withDuration: 1.5, delay: 0.6,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 1,
options: [], animations: {
self.containerDownloadButton.center.x += self.view.bounds.width
}, completion: nil)
UIView.animate(withDuration: 1.5, delay: 0.7,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 1,
options: [], animations: {
self.containerUploadButton.center.x += self.view.bounds.width
}, completion: nil)
UIView.animate(withDuration: 1.5, delay: 0.8,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 1,
options: [], animations: {
self.containerCallButton.center.x += self.view.bounds.width
}, completion: nil)
UIView.animate(withDuration: 1.5, delay: 0.9,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 1,
options: [], animations: {
self.containerIdleButton.center.x += self.view.bounds.width
}, completion: nil)
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
})
I'm animating the scale of a button using animateKeyframes in Swift 3 using the following code:
UIView.animateKeyframes(withDuration: 4, delay: 1, options: [.repeat, .allowUserInteraction, .calculationModeCubic], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.1, animations: {
self.myButton.transform = CGAffineTransform(scaleX: 1,y: 1)
})
UIView.addKeyframe(withRelativeStartTime: 0.1, relativeDuration: 0.1, animations: {
self.myButton.transform = CGAffineTransform(scaleX: 0.9,y: 0.9)
})
}, completion: nil)
What I need to do is add easing to each keyframe. I looked up something that uses the following code that can then be passed to animateKeyframes
let animationOptions: UIViewAnimationOptions = .curveEaseIn
let keyframeAnimationOptions: UIViewKeyframeAnimationOptions = UIViewKeyframeAnimationOptions(rawValue: animationOptions.rawValue)
However, it doesn't quite say exactly how to pass the keyframeAnimationOptions variable, and I can't seem to figure it out myself! Can anybody help?
You can use below code to call the keyframeAnimationOptions variable.
let keyframeAnimationOption=UIViewKeyframeAnimationOptions.CalculationModeCubic
UIView.animateKeyframesWithDuration(duration, delay: delay, options: keyframeAnimationOption, animations:
{
/////Your code //////
}, completion: nil)
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.