Estoy tratando de hacer una animación simple en Swift. Es un desvanecimiento.
Lo intenté:
self.myFirstLabel.alpha = 0
self.myFirstButton.alpha = 0
self.mySecondButton.alpha = 0
Luego tengo:
self.view.addSubview(myFirstLabel)
self.view.addSubview(myFirstButton)
self.view.addSubview(mySecondButton)
Y entonces:
UIView.animateWithDuration(1.5, animations: {
self.myFirstLabel.alpha = 1.0
self.myFirstButton.alpha = 1.0
self.mySecondButton.alpha = 1.0
})
Tengo todo esto en mi función viewDidLoad.
¿Cómo hago que esto funcione?
viewWillAppear
oviewDidAppear
como usted no sabe lo que pasa entre la vista que se carga y se muestra.Respuestas:
El problema es que está intentando iniciar la animación demasiado pronto en el ciclo de vida del controlador de vista. En
viewDidLoad
, la vista se acaba de crear y aún no se ha agregado a la jerarquía de vistas, por lo que intentar animar una de ellassubviews
en este punto produce malos resultados.Lo que realmente debería hacer es continuar configurando el alfa de la vista en
viewDidLoad
(o donde crea sus vistas), y luego esperarviewDidAppear
a que se llame al método :. En este punto, puede iniciar sus animaciones sin ningún problema.override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) UIView.animate(withDuration: 1.5) { self.myFirstLabel.alpha = 1.0 self.myFirstButton.alpha = 1.0 self.mySecondButton.alpha = 1.0 } }
fuente
viewWillAppear
más apropiado para esto?UIView.animateWithDuration(1.5, animations: { self.myFirstLabel.alpha = 1.0 return })
La respuesta de 0x7ffffff está bien y definitivamente es exhaustiva.
Como ventaja, te sugiero que hagas una extensión UIView, de esta manera:
public extension UIView { /** Fade in a view with a duration - parameter duration: custom animation duration */ func fadeIn(duration duration: NSTimeInterval = 1.0) { UIView.animateWithDuration(duration, animations: { self.alpha = 1.0 }) } /** Fade out a view with a duration - parameter duration: custom animation duration */ func fadeOut(duration duration: NSTimeInterval = 1.0) { UIView.animateWithDuration(duration, animations: { self.alpha = 0.0 }) } }
Swift-3
/// Fade in a view with a duration /// /// Parameter duration: custom animation duration func fadeIn(withDuration duration: TimeInterval = 1.0) { UIView.animate(withDuration: duration, animations: { self.alpha = 1.0 }) } /// Fade out a view with a duration /// /// - Parameter duration: custom animation duration func fadeOut(withDuration duration: TimeInterval = 1.0) { UIView.animate(withDuration: duration, animations: { self.alpha = 0.0 }) }
De esta manera, puede hacer esto en cualquier lugar de su código:
let newImage = UIImage(named: "") newImage.alpha = 0 // or newImage.fadeOut(duration: 0.0) self.view.addSubview(newImage) ... newImage.fadeIn()
¡La reutilización del código es importante!
fuente
La única solución rápida
Similar a la respuesta de Luca , utilizo una
UIView
extensión. En comparación con su solución, utilizoDispatchQueue.main.async
para asegurarme de que las animaciones se realicen en el hilo principal,alpha
parámetro para desvanecer a un valor específico yduration
parámetros opcionales para código más limpio.extension UIView { func fadeTo(_ alpha: CGFloat, duration: TimeInterval = 0.3) { DispatchQueue.main.async { UIView.animate(withDuration: duration) { self.alpha = alpha } } } func fadeIn(_ duration: TimeInterval = 0.3) { fadeTo(1.0, duration: duration) } func fadeOut(_ duration: TimeInterval = 0.3) { fadeTo(0.0, duration: duration) } }
Cómo usarlo:
// fadeIn() - always animates to alpha = 1.0 yourView.fadeIn() // uses default duration of 0.3 yourView.fadeIn(1.0) // uses custom duration (1.0 in this example) // fadeOut() - always animates to alpha = 0.0 yourView.fadeOut() // uses default duration of 0.3 yourView.fadeOut(1.0) // uses custom duration (1.0 in this example) // fadeTo() - used if you want a custom alpha value yourView.fadeTo(0.5) // uses default duration of 0.3 yourView.fadeTo(0.5, duration: 1.0)
fuente
Si desea una animación de fundido repetible, puede hacerlo usando
CABasicAnimation
como se muestra a continuación:Primero cree una práctica extensión UIView:
extension UIView { enum AnimationKeyPath: String { case opacity = "opacity" } func flash(animation: AnimationKeyPath ,withDuration duration: TimeInterval = 0.5, repeatCount: Float = 5){ let flash = CABasicAnimation(keyPath: animation.rawValue) flash.duration = duration flash.fromValue = 1 // alpha flash.toValue = 0 // alpha flash.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) flash.autoreverses = true flash.repeatCount = repeatCount layer.add(flash, forKey: nil) } }
Cómo usarlo:
// You can use it with all kind of UIViews e.g. UIButton, UILabel, UIImage, UIImageView, ... imageView.flash(animation: .opacity, withDuration: 1, repeatCount: 5) titleLabel.flash(animation: .opacity, withDuration: 1, repeatCount: 5)
fuente
import UIKit /* Here is simple subclass for CAAnimation which create a fadeIn animation */ class FadeInAdnimation: CABasicAnimation { override init() { super.init() keyPath = "opacity" duration = 2.0 fromValue = 0 toValue = 1 fillMode = CAMediaTimingFillMode.forwards isRemovedOnCompletion = false } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } } /* Example of usage */ class ViewController: UIViewController { weak var label: UILabel! override func loadView() { let view = UIView() view.backgroundColor = .white let label = UILabel() label.alpha = 0 label.frame = CGRect(x: 150, y: 200, width: 200, height: 20) label.text = "Hello World!" label.textColor = .black view.addSubview(label) self.label = label let button = UIButton(type: .custom) button.frame = CGRect(x: 0, y: 250, width: 300, height: 100) button.setTitle("Press to Start FadeIn", for: UIControl.State()) button.backgroundColor = .red button.addTarget(self, action: #selector(startFadeIn), for: .touchUpInside) view.addSubview(button) self.view = view } /* Animation in action */ @objc private func startFadeIn() { label.layer.add(FadeInAdnimation(), forKey: "fadeIn") } }
fuente
Rápido 5
Otras respuestas son correctas, pero en mi caso tengo que manejar otras propiedades también (
alpha
,animate
,completion
). Debido a esto, modifiqué un poco para exponer estos parámetros de la siguiente manera:extension UIView { /// Helper function to update view's alpha with animation /// - Parameter alpha: View's alpha /// - Parameter animate: Indicate alpha changing with animation or not /// - Parameter duration: Indicate time for animation /// - Parameter completion: Completion block after alpha changing is finished func set(alpha: CGFloat, animate: Bool, duration: TimeInterval = 0.3, completion: ((Bool) -> Void)? = nil) { let animation = { (view: UIView) in view.alpha = alpha } if animate { UIView.animate(withDuration: duration, animations: { animation(self) }, completion: { finished in completion?(finished) }) } else { layer.removeAllAnimations() animation(self) completion?(true) } } }
fuente