Jak animować właściwość textColor elementu UILabel?


82

Z jakiegoś powodu, kiedy próbuję animować textColor, to nie zadziała. TextColor po prostu nagle zmienia się z A na B. Czy można go animować, powiedzmy z czerwonego na czarny?

Odpowiedzi:


6

Ta odpowiedź jest przestarzała i nie jest dobrym rozwiązaniem na pierwotne pytanie. Odpowiedź @strange poniżej jest znacznie lepsza i powinna być używana zamiast tej odpowiedzi: https://stackoverflow.com/a/20892927/76559

// Stara odpowiedź poniżej

textColorNieruchomość nie jest określony jako animatable w docs, więc nie sądzę, można to zrobić za pomocą prostego bloku animacji UIView ...

Można to prawdopodobnie zrobić dość prymitywnie, NSTimerwypalając co kilka milisekund, za każdym razem ustawiając kolor stopniowo od jednego do drugiego.

Mówię, że jest to surowe, ponieważ wymagałoby tablicy lub innego pojemnika z ustawionymi wartościami kolorów przechodzącymi od koloru początkowego do koloru końcowego, i jestem pewien, że jest sposób, aby to zrobić za pomocą podstawowej animacji lub czegoś podobnego, po prostu nie robię wiem, co to jest.


lub: funkcja, która wyrzuca tablicę z wartościami RGB między A i B oraz określoną wartością procentową. Nie wiem jednak nic o algorytmach kolorów.
dontWatchMyProfile

oto dobre obejścia: tu i tutaj dzięki Annie Kareninie
szakal

4
Należy CADisplayLinkraczej używać NSTimeranimacji jazdy niż ręcznie, ponieważ jest ona zsynchronizowana z aktualizacjami wyświetlania. Zobacz sesję 236 WWDC 2014: Interruptible and Responsive Interactions w budynku około godziny 13:00.
Douglas Hill

NIE powinna to być już akceptowana odpowiedź, nawet jeśli była prawdą w tamtym czasie. zobacz odpowiedź dziwnego poniżej
bitwit

1
Przepełnienie stosu nie pozwoli mi usunąć tej przestarzałej odpowiedzi, ponieważ została zaakceptowana. Odpowiedź Checkout @ dziwna poniżej.
Jasarien

196

Zamiast tego, jeśli próbowałeś użyć przejścia przenikania na samym obiekcie w ten sposób, da ci to ładny efekt zanikania z jednego koloru na drugi:

Cel C

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

Szybki

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

Jest to lepsze niż używanie NSTimerów, CATextLayers i tak dalej z różnych powodów. CATextLayer nie ma odpowiedniej obsługi kerningu tekstu ani NSAttributedText, a NSTimery są opóźnione (plus jest za dużo kodu). Powyższa animacja przejścia załatwia sprawę i może być również użyta w animacji łańcucha. Miałem ten sam problem i wypróbowałem już powyższe rozwiązania, ale zamiast tego ten prosty kod działa cuda.


7
Ładne, eleganckie, właściwie najlepsze i najczystsze rozwiązanie.
maksa

17
Świetny. Działa w Swift tak samo:UIView.transitionWithView(creditsLabel, duration: 0.3, options: .TransitionCrossDissolve, animations: { self.creditsLabel.textColor = UIColor.redColor() }, completion: nil)
SimplGy

8
tylko uwaga: działa to tylko wtedy, gdy etykieta jest statyczna. Jeśli to zrobisz, a pozycja etykiety jest modyfikowana, animacja zanikania pokaże brzydki artefakt.
Lukas Petr,

Nie działa dla mnie na Xcode 10.2.1 i Swift 5. Poniższa metoda „shokaveli” działa
Martin

Szukałem sposobu, aby to zrobić w SwiftUI, ale wydaje się, że nie jest to obsługiwane w tym czasie.
philipp

58

Rozwiązanie Swift 4 :

UIView.transition(with: yourLabel, duration: 0.3, options: .transitionCrossDissolve, animations: {
  self.yourLabel.textColor = .red
}, completion: nil)

Uwaga, działa to tylko wtedy, gdy masz wystąpienie UILabeldla withwłaściwości. Jeśli zrobisz coś podobnego transition(with: outerView.label…)i spróbujesz umieścić to w środku, po cichu zawiedzie.
Sam Soffes

Z jakiegoś powodu nie działa na mnie. Podczas animacji nagle zmienia się zamiast stopniowo. :(
ScottyBlades

1
@ScottyBlades może robisz animację w wątku w tle? Spróbuj opakować kod UIView.transition w nawiasy DispatchQueue.main.async {}.
budiDino

1
FYI - Pierwszy raz, kiedy próbowałem, nie zadziałał, a to dlatego options: .easeInOut, że tak było , więc zmieniłem to na .transitionCrossDissolve i działałem.
LeoGalante

13

Powodem, dla którego textColor nie można animować, jest to, że UILabel używa zwykłego CALayer zamiast CATextLayer.

Aby umożliwić animację textColor (jak również tekst, czcionkę itp.), Możemy utworzyć podklasę UILabel, aby używała CATextLayer.

To sporo pracy, ale na szczęście już to zrobiłem :-)

W tym artykule można znaleźć pełne wyjaśnienie + zastępczy zamiennik oprogramowania typu open source dla UILabel


9

Możesz spróbować utworzyć inną instancję UILabel lub cokolwiek innego, co ma textColor, a następnie zastosować animację między tymi dwoma instancjami (ze starym textColor i tym z nowym textColor).


7

To była JEDYNA rzecz, która działała dla mnie:

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()

6

Oto mój kod do animacji koloru tekstu etykiety. Ważnym elementem jest ustalenie textColor do clearColor przed animacją

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

0

Dość łatwo znalazłem umieszczenie UIView pod etykietą i animowanie jego krycia. Etykietę należy dodać do tego widoku. Może nie jest to dobre rozwiązanie z punktu widzenia zużycia zasobów, ale całkiem proste.


0

zaktualizowany swift 3.0

Właśnie zmieniłem z komentarzy @budidino

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

0

Dzięki za odpowiedź @ Strange , działającą doskonale w Swift 5, Xcode 11 z niewielką zmianą składni. Animowałem kolor tekstu dla wielu etykiet UIL. Jeśli tak jest, spróbuj tego

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)
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.