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

82

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

dontWatchMyProfile
источник

Ответы:

6

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

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

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

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

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

Jasarien
источник
или: функция, которая выдает массив со значениями 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)
budiDino
источник
Обратите внимание: это работает, только если у вас есть экземпляр 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).

benasher44
источник
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 под меткой и анимировать его непрозрачность. К этому виду необходимо добавить метку. Может быть, не лучшее решение с точки зрения потребления ресурсов, но довольно простое.

Catchakos
источник
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)
}
Даниэль Ху
источник