As stated in the title, I am unable to get the UIButton to fade in on the ViewDidLoad method. Here is my code thus far:
ViewController.swift
import UIKit
import QuartzCore
class ViewController: UIViewController {
#IBOutlet weak var nextButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.nextButton.fadeIn(duration: 10.0, delay: 10.0)
}
}
UIViewExtensions.swift
import Foundation
import UIKit
extension UIView {
func fadeIn(duration: NSTimeInterval = 1.0, delay: NSTimeInterval = 0.0, completion: ((Bool) -> Void) = {(finished: Bool) -> Void in}) {
UIView.animateWithDuration(duration, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.alpha = 1.0
}, completion: completion) }
func fadeOut(duration: NSTimeInterval = 1.0, delay: NSTimeInterval = 0.0, completion: (Bool) -> Void = {(finished: Bool) -> Void in}) {
UIView.animateWithDuration(duration, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.alpha = 0.0
}, completion: completion)
}
}
You do not want to start any animations like a fade in, on the viewDidLoad. This method is called when the class is finished initializing (right after the init). It happens before the view is visible. You want to start animations in the viewDidAppear. This is called once the view is visible on the screen. When you start it in the viewDidLoad, it's already done the animation by the time it gets to the viewDidAppear, assuming of course you did the fade in over about .5 second.
Set you button alpha to 0 on storyboard,so that you can fade in.
Because,if your button alpha is 1,then you want to animate to 1,IOS do nothing
override func viewDidAppear(animated: Bool) {
self.button.fadeIn(duration: 3, delay: 0)
}
Related
I'm using the excellent answer here to implement a fade in for a text label.
However, I want to introduce a delay so I can sequentially fade in several text labels.
So far (taken from the answer), i'm using :
extension UIView {
func fadeIn(duration: TimeInterval = 1.0, delay: TimeInterval = 0.0, completion: #escaping ((Bool) -> Void) = {(finished: Bool) -> Void in}) {
UIView.animate(withDuration: duration, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.alpha = 1.0
}, completion: completion) }
}
and then implementing with :
override func viewDidLoad() {
self.line1Outlet.alpha = 0
self.line1Outlet.fadeIn(completion: {
(finished: Bool) -> Void in
})
}
I was thinking the best solution would be to implement the delay as a parameter in the extension so I could easily add a different delay to each label. (e.g.
override func viewDidLoad() {
self.line1Outlet.alpha = 0
//add a parameter here for the delay (here line 1 gets '1second' then line 2 could come in after 2seconds etc)
self.line1Outlet.delay = 1second
self.line1Outlet.fadeIn(completion: {
(finished: Bool) -> Void in
})
}
I've tried adding self.delay into the extension (underneath self.alpha) but that doesn't work and I'm not sure how to refactor that extension to allow what I'm after.
The answer to this would then be a reusable method of implementing sequential fades that hopefully would be useful to lots of other people!
In the extension you created, first add self.alpha = 0.0 at the top in fadeIn function, i.e.
extension UIView {
func fadeIn(duration: TimeInterval = 1.0, delay: TimeInterval = 0.0, completion: ((Bool)->())? = nil) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: .curveEaseIn, animations: {
self.alpha = 1.0
}, completion: completion)
}
}
Now lets assume you've 3 labels in your view, i.e.
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
Add animation to the labels in sequence like,
self.label1.fadeIn(delay: 0.1) { _ in
self.label2.fadeIn(delay: 0.2, completion: { _ in
self.label3.fadeIn(delay: 0.3, completion: { _ in
print("Done All")
})
})
}
Since the duration parameter in fadeIn method is having a default value, we can avoid that.
The way you're calling fadeIn is one way of calling it. Since the method contains multiple default params, it can be called in other ways as well.
Read more about default parameters here.
Edit:
For hiding the labels initially, set the alpha of all labels as 0 in storyboard itself.
I am attempting to animate the alpha of a UIImage after 3 seconds has passed. By default the alpha is set to 0 and after 3 seconds, the alpha should change to 1, thus displaying the image to the user. My code I wrote for my animation does set the alpha to 0, but I am unable to change the the alpha to 1 after 3 seconds. I am newer to swift and not sure where I am going wrong with this. Here is my code.
import UIKit
class WelcomeOneViewController: UIViewController {
#IBOutlet weak var swipeImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
swipeImageView.alpha = 0
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
displaySwipeView()
}
func displaySwipeView() {
UIView.animate(withDuration: 1.0, delay: 3.0, options: .beginFromCurrentState, animations: {
DispatchQueue.main.async { [weak self] in
self?.swipeImageView.alpha = 1
}
}, completion: nil)
}
}
Try it with this code:
import UIKit
class WelcomeOneViewController: UIViewController {
#IBOutlet weak var swipeImageView: UIImageView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
swipeImageView.alpha = 0
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
displaySwipeView()
}
func displaySwipeView() {
swipeImageView.alpha = 0
UIView.animate(withDuration: 1.0, delay: 3.0, options: [], animations: {
self.swipeImageView.alpha = 1
}, completion: nil)
}
}
Try doing it on main queue like this:
func displaySwipeView() {
UIView.animate(withDuration: 1.0, delay: 3.0, options: .beginFromCurrentState, animations: {
DispatchQueue.main.async { [weak self] in
self?.swipeImageView.alpha = 1
}
}, completion: nil)
}
Hope it helps!!
I'm a very new-to-code learner. I've been taking some online courses, and came across this project recently.
I basically copied the code as I saw it on the screen, as the project files weren't available to download.
The animation is supposed to bring the UILabels from outside the view and position them within the view.
What seems to happen however, is the labels are starting within the view screen and animate outward and beyond.
I've copied the project below. Any help is so very appreciated.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var helloWorld: UILabel!
#IBOutlet weak var secondLabel: UILabel!
#IBOutlet weak var hiddenLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
helloWorld.center.y -= view.bounds.height
secondLabel.center.y += view.bounds.height
hiddenLabel.alpha = 0.0
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// Animate Hello World label
UIView.animateWithDuration(1.5, animations: {
self.helloWorld.center.y += self.view.bounds.height
}, completion: { finished in
self.secondAnimation()
})
// Animate background color change
UIView.animateWithDuration(2.0, delay: 1.5, options: [], animations: {
self.view.backgroundColor = UIColor.yellowColor()
}, completion:nil)
}
// Animate second Label
func secondAnimation() {
UIView.animateWithDuration(1.5, delay: 0.0, options: [], animations: { () -> Void in
self.secondLabel.center.y -= self.view.bounds.height
}, completion:nil)
}
func backgroundColor() {
UIView.animateWithDuration(2.5, animations: {
self.view.backgroundColor = UIColor.blackColor()
}, completion: nil)
UIView.animateWithDuration(1.0, delay: 1.5, options: [], animations: {
self.hiddenLabel.alpha = 1.0
}, completion:nil)
}
}
I would check hello world.center.y value in viewWillAppear, before you subtract the view.bounds.height. If center.y value is large and positive, then the subtraction might be setting the center.y value to be inside of the view. If this is the case, then you would want to change the subtraction in viewWillAppear to addition and then the addition in the viewDidAppear animation to subtraction.
Setting animation to fade in and out repeatedly.
'viewSmall' and 'viewBig' are UIImageViews.
view storyboard shot
class TestViewController: UIViewController {
#IBOutlet weak var viewBig: UIImageView!
#IBOutlet weak var viewSmall: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
animate()
}
func animate() {
UIView.animateWithDuration(0.5,
delay: 0,
options: [.Repeat, .Autoreverse],
animations: {
self.viewSmall.alpha = 0
},
completion: nil)
UIView.animateWithDuration(0.5,
delay: 0,
options: [.Repeat, .Autoreverse],
animations: {
self.viewBig.alpha = 0
},
completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This code doesn't animate on a only few view controllers, and the view controllers seem independent, no segue to other view controllers, on my guess. Because this code works perfectly on view controllers connected to navigation view controller.
How can I make it on independent view controller?
Please help.
Found a brilliant solution.
Used dispatch_after to catch duration and delay.
func animate(){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), {
// Animate the transition
UIView.animateWithDuration(0.5,
delay: 0,
options: [.Repeat, .Autoreverse],
animations: {
self.viewSmall.alpha = 0
},
completion: nil)
UIView.animateWithDuration(0.5,
delay: 0,
options: [.Repeat, .Autoreverse],
animations: {
self.viewBig.alpha = 0
},
completion: nil)
})
}
Source from:
Swift UIView animateWithDuration completion closure called immediately
so what I wanna do is to restart the animation, when it's completed and I pressed the Restart button.
Here's what I've got right now.
It starts like that:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var fillView: UIView!
#IBAction func startAnimation(sender: AnyObject) {
self.animationBackground(fillView, animationTime: Float(15))
}
#IBAction func restartAnimation(sender: AnyObject) {
let layerRectangle = fillView.layer
restartLayer(layerRectangle)
}
func animationBackground(view:UIView,animationTime:Float){
UIView.animateWithDuration(NSTimeInterval(animationTime), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: {
view.transform = CGAffineTransformMakeTranslation(0.0, self.screenSize.height-67)
},completion:nil)
}
func restartLayer(layer:CALayer){
layer.beginTime = 0.0
layer.speed = 0.0
}
}
The restart function works only while animation is playing. But when it's completed that doesn't restart the animation from the beginning. Any tips on how to restart the animation on button click but only when it's already done?
I have already written above.. by the way:
func animationBackground(view:UIView,animationTime:Float){
self.fillView.transform = CGAffineTransformIdentity
UIView.animateWithDuration(NSTimeInterval(animationTime), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: {
view.transform = CGAffineTransformMakeTranslation(0.0, self.screenSize.height-67)
},completion:nil)
}
You have tranlsated the position and the frame (position). So once the animation has completed you have to restore the frame to its original position. You can restore the frame in completion block of the animation.
here the example:
UIView.animateWithDuration(1, animations: { () -> Void in
self.fillView.transform = CGAffineTransformMakeTranslation(0, 40)
}) { (end) -> Void in
self.fillView.transform = CGAffineTransformIdentity
}
You can you set transform to CGAffineTransformIdentity just before starting the animation.