Как анимировать свойство textColor UILabel?


82

По какой-то причине, когда я пытаюсь анимировать textColor, это не сработает. TextColor внезапно меняется с A на B. Можно ли его оживить, скажем, от красного до черного?

Ответы:


6

Этот ответ устарел и не является хорошим решением исходного вопроса. Ответ @strange ниже намного лучше, и его следует использовать вместо этого ответа: https://stackoverflow.com/a/20892927/76559

// Старый ответ ниже

Это textColorсвойство не указано в документации как анимируемое, поэтому я не думаю, что вы можете сделать это с помощью простого блока анимации UIView ...

Вероятно, это можно было бы сделать довольно грубо, NSTimerобжигая каждые пару миллисекунд, каждый раз постепенно меняя цвет от одного к другому.

Я говорю, что это грубо, потому что для этого потребуется массив или другой контейнер предустановленных значений цвета, идущих от начального цвета до конечного цвета, и я уверен, что есть способ сделать это, используя базовую анимацию или что-то в этом роде, я просто не не знаю что это.


или: функция, которая выдает массив со значениями RGB между A и B и заданным процентом. Хотя ничего не знаю о цветовых алгоритмах.
dontWatchMyProfile

вот хорошие обходные пути: здесь и здесь спасибо Анне Карениной
шакал

4
Вы должны использовать, CADisplayLinkа не NSTimerуправлять анимацией вручную, потому что она синхронизируется с обновлениями дисплея. См. WWDC 2014 Сессия 236: Создание прерываемого и отзывчивого взаимодействия примерно в 13:00.
Дуглас Хилл

это уже НЕ должен быть принятым ответом, даже если он был правдой в то время. см. странный ответ ниже
bitwit

1
Stack Overflow не позволит мне удалить этот устаревший ответ, поскольку он был принят. Оформить заказ @ странный ответ ниже.
Jasarien 08

196

Вместо этого, если вы пытались использовать переход кроссфейда на самом объекте, как этот, это даст вам хороший эффект постепенного исчезновения от одного цвета к другому:

Цель C

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

Swift

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

Это лучше, чем использование NSTimers, CATextLayers и т. Д. По разным причинам. CATextLayer не имеет надлежащей поддержки текстового кернинга или NSAttributedText, а NSTimers отстают (плюс слишком много кода). Приведенная выше анимация перехода делает свое дело, и ее также можно использовать в цепной анимации. У меня была такая же проблема, и я уже пробовал решения выше, но вместо этого этот простой код творит чудеса.


7
Красивое, элегантное, на самом деле лучшее и чистое решение.
макса

17
Отлично. Точно так же работает в Swift:UIView.transitionWithView(creditsLabel, duration: 0.3, options: .TransitionCrossDissolve, animations: { self.creditsLabel.textColor = UIColor.redColor() }, completion: nil)
SimplGy

8
просто примечание: это работает, только когда метка статична. Если вы сделаете это, и позиция метки будет изменена, в анимации исчезновения появится некрасивый артефакт.
Лукас Петр

У меня не работает на Xcode 10.2.1 и Swift 5. Метод shokaveli, приведенный ниже, работает
Мартин

Я искал способ сделать это в SwiftUI, но в то время он не поддерживается.
Филипп

59

Решение Swift 4 :

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

Обратите внимание: это работает, только если у вас есть экземпляр UILabelдля withсвойства. Если вы сделаете что-то подобное transition(with: outerView.label…)и попытаетесь установить это внутри, это потерпит неудачу.
Sam Soffes 02

У меня почему-то не работает. Это изменение происходит внезапно, а не постепенно во время анимации. :(
ScottyBlades

1
@ScottyBlades, может быть, вы делаете анимацию в фоновом потоке? Попробуйте заключить код UIView.transition в скобки DispatchQueue.main.async {}.
budiDino

1
К вашему сведению - первый раз, когда я попробовал, не сработало, и это было потому, что у меня было options: .easeInOut, поэтому я изменил его на .transitionCrossDissolve и работал.
LeoGalante

13

Причина того, что textColor не анимируется, заключается в том, что UILabel использует обычный CALayer вместо CATextLayer.

Чтобы сделать textColor анимируемым (а также текст, шрифт и т. Д.), Мы можем создать подкласс UILabel, чтобы он использовал CATextLayer.

Это довольно большая работа, но, к счастью, я ее уже сделал :-)

Вы можете найти полное объяснение + замену UILabel с открытым исходным кодом в этой статье.


9

Вы можете попробовать создать другой экземпляр UILabel или того, что имеет textColor, а затем применить анимацию между этими двумя экземплярами (со старым textColor и одним с новым textColor).


7

Это было ЕДИНСТВЕННОЕ, что сработало для меня:

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

Вот мой код для анимации цвета текста метки. Важной частью является создание TextColor для clearColor перед тем анимации

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

0

Мне было довольно легко разместить UIView под меткой и анимировать его непрозрачность. К этому виду необходимо добавить метку. Может быть, не лучшее решение с точки зрения потребления ресурсов, но довольно простое.


0

обновлен Swift 3.0

Я только что перешел из комментариев @budidino

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

0

Спасибо за @ Странный ответ «S, прекрасно работает в Swift 5, Xcode 11 с изменением немного синтаксиса. Я анимировал цвет текста для нескольких UILabels, если это тоже ваш случай, попробуйте это

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)
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.