Ustawiam nową wartość tekstową na UILabel
. Obecnie nowy tekst wygląda dobrze. Chciałbym jednak dodać animację, gdy pojawi się nowy tekst. Zastanawiam się, co mogę zrobić, aby ożywić wygląd nowego tekstu.
ios
objective-c
ipad
uilabel
caanimation
Joo Park
źródło
źródło
Odpowiedzi:
Zastanawiam się, czy działa i działa idealnie!
Cel C
[UIView transitionWithView:self.label duration:0.25f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!"; } completion:nil];
Swift 3, 4, 5
UIView.transition(with: label, duration: 0.25, options: .transitionCrossDissolve, animations: { [weak self] in self?.label.text = (arc4random()() % 2 == 0) ? "One" : "Two" }, completion: nil)
źródło
Cel C
Aby osiągnąć prawdziwe przejście przez rozpuszczanie (stare etykiety zanikają, a nowe znikają), nie chcesz, aby zanikanie stało się niewidoczne. Spowodowałoby to niepożądane migotanie, nawet jeśli tekst byłby niezmieniony .
Zamiast tego użyj tego podejścia:
CATransition *animation = [CATransition animation]; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; animation.type = kCATransitionFade; animation.duration = 0.75; [aLabel.layer addAnimation:animation forKey:@"kCATransitionFade"]; // This will fade: aLabel.text = "New"
Zobacz także: Animowanie tekstu UILabel między dwoma liczbami?
Demonstracja w iOS 10, 9, 8:
Testowane z Xcode 8.2.1 i 7.1 , ObjectiveC na iOS 10 do 8.0 .
► Aby pobrać cały projekt, wyszukaj SO-3073520 w Swift Recipes .
źródło
-addAnimation:forKey
do tej etykiety, a następnie zmieniasz tekst etykiety.Szybki 4
Właściwym sposobem na zanikanie UILabel (lub dowolnego UIView w tym przypadku) jest użycie pliku
Core Animation Transition
. To nie będzie migotać ani nie wyblaknie, jeśli zawartość pozostanie niezmieniona.Przenośnym i czystym rozwiązaniem jest użycie języka
Extension
Swift (wywołanie przed zmianą widocznych elementów)// Usage: insert view.fadeTransition right before changing content extension UIView { func fadeTransition(_ duration:CFTimeInterval) { let animation = CATransition() animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) animation.type = CATransitionType.fade animation.duration = duration layer.add(animation, forKey: CATransitionType.fade.rawValue) } }
Inwokacja wygląda następująco:
// This will fade aLabel.fadeTransition(0.4) aLabel.text = "text"
► Znajdź to rozwiązanie w GitHub i dodatkowe informacje na temat Swift Recipes .
źródło
MIT
licencja gwarantuje, że Twój Cocoapod może być swobodnie używany przez wszystkich i każdego.od iOS4 można to oczywiście zrobić za pomocą bloków:
[UIView animateWithDuration:1.0 animations:^{ label.alpha = 0.0f; label.text = newText; label.alpha = 1.0f; }];
źródło
Oto kod, dzięki któremu to zadziała.
[UIView beginAnimations:@"animateText" context:nil]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; [UIView setAnimationDuration:1.0f]; [self.lbl setAlpha:0]; [self.lbl setText:@"New Text"; [self.lbl setAlpha:1]; [UIView commitAnimations];
źródło
Rozwiązanie rozszerzenia UILabel
extension UILabel{ func animation(typing value:String,duration: Double){ let characters = value.map { $0 } var index = 0 Timer.scheduledTimer(withTimeInterval: duration, repeats: true, block: { [weak self] timer in if index < value.count { let char = characters[index] self?.text! += "\(char)" index += 1 } else { timer.invalidate() } }) } func textWithAnimation(text:String,duration:CFTimeInterval){ fadeTransition(duration) self.text = text } //followed from @Chris and @winnie-ru func fadeTransition(_ duration:CFTimeInterval) { let animation = CATransition() animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) animation.type = CATransitionType.fade animation.duration = duration layer.add(animation, forKey: CATransitionType.fade.rawValue) } }
Funkcja Simply Called wg
uiLabel.textWithAnimation(text: "text you want to replace", duration: 0.2)
Dzięki za wszystkie wskazówki. Mam nadzieję, że to pomoże w dłuższej perspektywie
źródło
Wersja Swift 4.2 powyższego rozwiązania SwiftArchitect (działa świetnie):
// Usage: insert view.fadeTransition right before changing content extension UIView { func fadeTransition(_ duration:CFTimeInterval) { let animation = CATransition() animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) animation.type = CATransitionType.fade animation.duration = duration layer.add(animation, forKey: CATransitionType.fade.rawValue) } }
Wezwanie:
// This will fade aLabel.fadeTransition(0.4) aLabel.text = "text"
źródło
Swift 2.0:
UIView.transitionWithView(self.view, duration: 1.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: { self.sampleLabel.text = "Animation Fade1" }, completion: { (finished: Bool) -> () in self.sampleLabel.text = "Animation Fade - 34" })
LUB
UIView.animateWithDuration(0.2, animations: { self.sampleLabel.alpha = 1 }, completion: { (value: Bool) in self.sampleLabel.alpha = 0.2 })
źródło
Dzięki Swift 5 możesz wybrać jeden z dwóch poniższych przykładów kodu Playground, aby animować
UILabel
zmiany tekstu za pomocą animacji rozpuszczania krzyżowego.# 1. Korzystanie
UIView
ztransition(with:duration:options:animations:completion:)
metody klasyimport UIKit import PlaygroundSupport class ViewController: UIViewController { let label = UILabel() override func viewDidLoad() { super.viewDidLoad() label.text = "Car" view.backgroundColor = .white view.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:))) view.addGestureRecognizer(tapGesture) } @objc func toggle(_ sender: UITapGestureRecognizer) { let animation = { self.label.text = self.label.text == "Car" ? "Plane" : "Car" } UIView.transition(with: label, duration: 2, options: .transitionCrossDissolve, animations: animation, completion: nil) } } let controller = ViewController() PlaygroundPage.current.liveView = controller
# 2. Używanie
CATransition
iCALayer
„Sadd(_:forKey:)
metodyimport UIKit import PlaygroundSupport class ViewController: UIViewController { let label = UILabel() let animation = CATransition() override func viewDidLoad() { super.viewDidLoad() label.text = "Car" animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) // animation.type = CATransitionType.fade // default is fade animation.duration = 2 view.backgroundColor = .white view.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:))) view.addGestureRecognizer(tapGesture) } @objc func toggle(_ sender: UITapGestureRecognizer) { label.layer.add(animation, forKey: nil) // The special key kCATransition is automatically used for transition animations label.text = label.text == "Car" ? "Plane" : "Car" } } let controller = ViewController() PlaygroundPage.current.liveView = controller
źródło
Rozwiązanie Swift 4.2 (pobranie odpowiedzi 4.0 i aktualizacja dla nowych wyliczeń do kompilacji)
extension UIView { func fadeTransition(_ duration:CFTimeInterval) { let animation = CATransition() animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) animation.type = CATransitionType.fade animation.duration = duration layer.add(animation, forKey: CATransitionType.fade.rawValue) } } func updateLabel() { myLabel.fadeTransition(0.4) myLabel.text = "Hello World" }
źródło
Domyślne systemowe wartości 0,25 for
duration
i .curveEaseInEaseOut fortimingFunction
są często preferowane ze względu na spójność między animacjami i można je pominąć:let animation = CATransition() label.layer.add(animation, forKey: nil) label.text = "New text"
co jest tym samym, co napisanie tego:
let animation = CATransition() animation.duration = 0.25 animation.timingFunction = .curveEaseInEaseOut label.layer.add(animation, forKey: nil) label.text = "New text"
źródło
Jest to metoda rozszerzenia C # UIView oparta na kodzie @ SwiftArchitect. Kiedy używany jest układ automatyczny i kontrolki muszą się poruszać w zależności od tekstu etykiety, ten kod wywołujący używa Superviewu etykiety jako widoku przejścia zamiast samej etykiety. Dodałem wyrażenie lambda do akcji, aby było bardziej hermetyczne.
public static void FadeTransition( this UIView AView, double ADuration, Action AAction ) { CATransition transition = new CATransition(); transition.Duration = ADuration; transition.TimingFunction = CAMediaTimingFunction.FromName( CAMediaTimingFunction.Linear ); transition.Type = CATransition.TransitionFade; AView.Layer.AddAnimation( transition, transition.Type ); AAction(); }
Kod telefoniczny:
labelSuperview.FadeTransition( 0.5d, () => { if ( condition ) label.Text = "Value 1"; else label.Text = "Value 2"; } );
źródło
Jeśli chcesz to zrobić
Swift
z opóźnieniem, spróbuj tego:delay(1.0) { UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: { self.yourLabel.text = "2" }, completion: { finished in self.delay(1.0) { UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: { self.yourLabel.text = "1" }, completion: { finished in }) } }) }
korzystając z funkcji stworzonej przez @matt - https://stackoverflow.com/a/24318861/1982051 :
func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) }
co stanie się tym w Swift 3
źródło
Jest jeszcze jedno rozwiązanie, aby to osiągnąć. Zostało to opisane tutaj . Pomysł polega na podklasowaniu
UILabel
i nadpisywaniuaction(for:forKey:)
funkcji w następujący sposób:class LabelWithAnimatedText: UILabel { override var text: String? { didSet { self.layer.setValue(self.text, forKey: "text") } } override func action(for layer: CALayer, forKey event: String) -> CAAction? { if event == "text" { if let action = self.action(for: layer, forKey: "backgroundColor") as? CAAnimation { let transition = CATransition() transition.type = kCATransitionFade //CAMediatiming attributes transition.beginTime = action.beginTime transition.duration = action.duration transition.speed = action.speed transition.timeOffset = action.timeOffset transition.repeatCount = action.repeatCount transition.repeatDuration = action.repeatDuration transition.autoreverses = action.autoreverses transition.fillMode = action.fillMode //CAAnimation attributes transition.timingFunction = action.timingFunction transition.delegate = action.delegate return transition } } return super.action(for: layer, forKey: event) } }
Przykłady użycia:
// do not forget to set the "Custom Class" IB-property to "LabelWithAnimatedText" // @IBOutlet weak var myLabel: LabelWithAnimatedText! // ... UIView.animate(withDuration: 0.5) { myLabel.text = "I am animated!" }
myLabel.text = "I am not animated!"
źródło