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.
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.
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)
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 .
-addAnimation:forKey
do tej etykiety, a następnie zmieniasz tekst etykiety.
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 .
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;
}];
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];
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
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"
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
})
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.
UIView
z transition(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
CATransition
i CALayer
„S add(_: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
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"
}
Domyślne systemowe wartości 0,25 for duration
i .curveEaseInEaseOut for timingFunction
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"
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";
} );
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
func delay(_ delay:Double, closure:()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.after(when: when, execute: closure)
}
Jest jeszcze jedno rozwiązanie, aby to osiągnąć. Zostało to opisane tutaj . Pomysł polega na podklasowaniu UILabel
i nadpisywaniu action(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!"