Próbuję zrobić prostą animację w Swift. To zanikanie.
Próbowałem:
self.myFirstLabel.alpha = 0
self.myFirstButton.alpha = 0
self.mySecondButton.alpha = 0
Wtedy ja mam:
self.view.addSubview(myFirstLabel)
self.view.addSubview(myFirstButton)
self.view.addSubview(mySecondButton)
I wtedy:
UIView.animateWithDuration(1.5, animations: {
self.myFirstLabel.alpha = 1.0
self.myFirstButton.alpha = 1.0
self.mySecondButton.alpha = 1.0
})
Mam to wszystko w mojej funkcji viewDidLoad.
Jak to działa?
viewWillAppear
lub,viewDidAppear
ponieważ nie wiesz, co się dzieje między załadowaniem i wyświetleniem widoku.Odpowiedzi:
Problem polega na tym, że próbujesz rozpocząć animację zbyt wcześnie w cyklu życia kontrolera widoku. W
viewDidLoad
programie widok został właśnie utworzony i nie został jeszcze dodany do hierarchii widoków, więc próba animowania jednego z jego widokówsubviews
w tym momencie daje złe wyniki.To, co naprawdę powinieneś robić, to kontynuowanie ustawiania alfa widoku
viewDidLoad
(lub miejsca, w którym tworzysz swoje widoki), a następnie czekanie naviewDidAppear
wywołanie metody:. W tym momencie możesz bez problemu rozpocząć animacje.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 } }
źródło
viewWillAppear
jest do tego bardziej odpowiedni?UIView.animateWithDuration(1.5, animations: { self.myFirstLabel.alpha = 1.0 return })
Odpowiedź 0x7ffffff jest w porządku i zdecydowanie wyczerpująca.
Jako plus proponuję zrobić rozszerzenie UIView w ten sposób:
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 }) }
W ten sposób możesz to zrobić w dowolnym miejscu kodu:
let newImage = UIImage(named: "") newImage.alpha = 0 // or newImage.fadeOut(duration: 0.0) self.view.addSubview(newImage) ... newImage.fadeIn()
Ponowne wykorzystanie kodu jest ważne!
źródło
Tylko szybkie rozwiązanie
Podobnie jak w przypadku odpowiedzi Luca , używam
UIView
rozszerzenia. W porównaniu z jego rozwiązaniem, którego używam,DispatchQueue.main.async
aby upewnić się, że animacje są wykonywane w głównym wątku,alpha
parametr do zanikania do określonej wartości i opcjonalneduration
parametry dla czystszego kodu.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) } }
Jak tego użyć:
// 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)
źródło
Jeśli chcesz powtarzać animację zanikania, możesz to zrobić, używając
CABasicAnimation
poniższego:Najpierw utwórz przydatne rozszerzenie 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) } }
Jak tego użyć:
// 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)
źródło
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") } }
źródło
Szybki 5
Inne odpowiedzi są poprawne, ale w moim przypadku muszę obsługiwać również inne właściwości (
alpha
,animate
,completion
). Z tego powodu zmodyfikowałem trochę, aby wyeksponować te parametry jak poniżej: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) } } }
źródło