Wie animiere ich die textColor-Eigenschaft eines UILabels?

82

Aus irgendeinem Grund funktioniert es nicht, wenn ich versuche, textColor zu animieren. Die Textfarbe ändert sich plötzlich von A nach B. Ist es möglich, sie zu animieren, beispielsweise von Rot zu Schwarz?

dontWatchMyProfile
quelle

Antworten:

6

Diese Antwort ist veraltet und keine gute Lösung für die ursprüngliche Frage. Die Antwort von @strange unten ist viel besser und sollte anstelle dieser Antwort verwendet werden: https://stackoverflow.com/a/20892927/76559

// Alte Antwort unten

Das textColor Eigenschaft ist in den Dokumenten nicht als animierbar angegeben, daher glaube ich nicht, dass Sie dies mit einem einfachen UIView-Animationsblock tun können ...

Dies könnte wahrscheinlich ziemlich grob mit einem NSTimerBrennen alle paar Millisekunden geschehen , wobei jedes Mal die Farbe allmählich von einer zur anderen eingestellt wird.

Ich sage, das ist grob, weil es ein Array oder einen anderen Container mit voreingestellten Farbwerten erfordern würde, die von der Startfarbe bis zur Endfarbe reichen, und ich bin sicher, dass es eine Möglichkeit gibt, dies mithilfe der Kernanimation oder so etwas zu tun Ich weiß nicht was es ist.

Jasarien
quelle
oder: eine Funktion, die ein Array mit RGB-Werten zwischen A und B und einem bestimmten Prozentsatz ausgibt. Ich weiß jedoch nichts über Farbalgorithmen.
dontWatchMyProfile
Hier sind gute Workarounds: hier und hier danke an Anna Karenina
Schakal
4
Sie sollten Animationen nicht manuell steuern, CADisplayLinksondern verwenden, NSTimerda sie mit Anzeigeaktualisierungen synchronisiert sind. Siehe WWDC 2014, Sitzung 236: Aufbau unterbrechbarer und reaktionsfähiger Interaktionen um ca. 13:00 Uhr.
Douglas Hill
Dies sollte NICHT länger die akzeptierte Antwort sein, selbst wenn dies zu diesem Zeitpunkt der Fall war. siehe seltsame Antwort unten
Bitwit
Durch Stapelüberlauf kann ich diese veraltete Antwort nicht löschen, da sie akzeptiert wurde. Die Antwort von Checkout @ odd unten.
Jasarien
192

Wenn Sie stattdessen versucht haben, einen Überblendungsübergang für das Objekt selbst wie folgt zu verwenden, erhalten Sie einen schönen Einblendeffekt von einer Farbe zur anderen:

Ziel c

[UIView transitionWithView:myLabel duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    myLabel.textColor = NEW_COLOR;
} completion:^(BOOL finished) {
}];

Schnell

UIView.transitionWithView(creditsLabel, duration: 0.25, options: .TransitionCrossDissolve, animations: {     
    self.creditsLabel.textColor = UIColor.redColor() 
}, 
completion: nil)

Dies ist aus verschiedenen Gründen besser als die Verwendung von NSTimern, CATextLayers usw. CATextLayer unterstützt Textkerning oder NSAttributedText nicht ordnungsgemäß, und NSTimer sind verzögert (und es gibt zu viel Code). Die obige Übergangsanimation erledigt den Trick und kann auch in einer Kettenanimation verwendet werden. Ich hatte das gleiche Problem und habe bereits die oben genannten Lösungen ausprobiert, aber dieser einfache Code wirkt stattdessen Wunder.

seltsam
quelle
7
Schön, elegant, eigentlich die beste und sauberste Lösung.
Maksa
17
Toll. Funktioniert in Swift UIView.transitionWithView(creditsLabel, duration: 0.3, options: .TransitionCrossDissolve, animations: { self.creditsLabel.textColor = UIColor.redColor() }, completion: nil)
trotzdem
8
Nur ein Hinweis: Dies funktioniert nur, wenn das Etikett statisch ist. Wenn Sie dies tun und die Position des Etiketts geändert wird, zeigt die Ausblendanimation hässliche Artefakte.
Lukas Petr
Funktioniert nicht für mich unter Xcode 10.2.1 und Swift 5. Die unten stehende Shokaveli-Methode funktioniert
Martin
Ich habe nach einer Möglichkeit gesucht, dies in SwiftUI zu tun, aber es scheint derzeit nicht unterstützt zu werden.
Philipp
56

Swift 4- Lösung:

UIView.transition(with: yourLabel, duration: 0.3, options: .transitionCrossDissolve, animations: {
  self.yourLabel.textColor = .red
}, completion: nil)
Budidino
quelle
Beachten Sie, dass dies nur funktioniert, wenn Sie eine Instanz UILabelfür die withEigenschaft haben. Wenn Sie so etwas tun transition(with: outerView.label…)und versuchen, es in sich aufzunehmen, schlägt dies lautlos fehl.
Sam Soffes
Funktioniert bei mir aus irgendeinem Grund nicht. Während der Animation wird die Änderung plötzlich statt schrittweise vorgenommen. :(
ScottyBlades
1
@ScottyBlades Vielleicht machst du die Animation im Hintergrund-Thread? Versuchen Sie, den UIView.transition-Code in die Klammern DispatchQueue.main.async {} zu packen.
Budidino
1
Zu Ihrer Information: Das erste Mal habe ich versucht, nicht zu funktionieren, und das lag daran options: .easeInOut, dass ich es getan habe , also habe ich es geändert .transitionCrossDissolve und gearbeitet.
LeoGalante
13

Der Grund dafür, dass textColor nicht animierbar ist, ist, dass UILabel anstelle eines CATextLayer einen regulären CALayer verwendet.

Um textColor animierbar zu machen (sowie Text, Schriftart usw.), können wir UILabel in Unterklassen unterteilen, damit es einen CATextLayer verwendet.

Das ist ziemlich viel Arbeit, aber zum Glück habe ich es schon getan :-)

Eine vollständige Erklärung + einen Open-Source-Ersatz für UILabel finden Sie in diesem Artikel

Adamsiton
quelle
9

Sie können versuchen, eine andere Instanz des UILabels oder was auch immer mit der Textfarbe zu erstellen, und dann die Animation zwischen diesen beiden Instanzen anwenden (die mit der alten Textfarbe und die mit der neuen Textfarbe).

benasher44
quelle
7

Dies war das EINZIGE, was für mich funktioniert hat:

let changeColor = CATransition()
changeColor.duration = 1

CATransaction.begin()

CATransaction.setCompletionBlock {
    selected.label.layer.addAnimation(changeColor, forKey: nil)
    selected.label.textColor = .blackColor()
}

selected.nameLabel.textColor = .redColor()

CATransaction.commit()
Shokaveli
quelle
6

Hier ist mein Code zum Animieren der Etikettentextfarbe. Der wichtige Teil besteht darin, textColor vor der Animation auf clearColor zu setzen

label.textColor = [UIColor clearColor];
[UIView transitionWithView:label duration:duration/4 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    label.textColor = self.highlightedCellPrimaryTextColor;
} completion:^(BOOL finished) { }];
Servalex
quelle
0

Ich fand es ziemlich einfach, ein UIView unter dem Etikett zu platzieren und seine Deckkraft zu animieren. Das Etikett muss dieser Ansicht hinzugefügt werden. Vielleicht keine gute Lösung aus Sicht des Ressourcenverbrauchs, aber ziemlich einfach.

catchakos
quelle
0

aktualisiert schnell 3.0

Ich habe mich gerade von den Kommentaren von @budidino geändert

UIView.transition(with: my.label, duration: 0.3, options: .transitionCrossDissolve, animations: { my.label.textColor = .black }, completion: nil)
Shawn Baek
quelle
0

Vielen Dank für die Antwort von @ Strange , die in Swift 5, Xcode 11 mit einer geringfügigen Änderung der Syntax perfekt funktioniert. Ich habe die Textfarbe für mehrere UILabels animiert. Wenn dies auch Ihr Fall ist, versuchen Sie dies

for label in [label1, label2, ...] as [UILabel] { // loop through a @IBOutlet UILabel array
        UIView.transition(with: label, duration: 0.3, options: .transitionCrossDissolve, animations: {
            label.textColor = .label
        }, completion: nil)
}
Daniel Hu
quelle