Як анімувати властивість textColor UILabel?


82

З якоїсь причини, коли я намагаюся анімувати textColor, це не спрацює. Колір тексту просто раптово змінюється з А на В. Чи можна його анімувати, скажімо від червоного до чорного?

Відповіді:


6

Ця відповідь застаріла і не є гарним рішенням для вихідного питання. Відповідь @strange нижче набагато краща і її слід використовувати замість цієї відповіді: https://stackoverflow.com/a/20892927/76559

// Стара відповідь нижче

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

Це, мабуть, можна було зробити досить грубо, NSTimerвистрілюючи кожні пару мілісекунд, кожного разу встановлюючи колір поступово від одного до іншого.

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


або: функція, яка викидає масив із значеннями RGB між A і B та заданим відсотком. Не знаю нічого про кольорові алгоритми.
dontWatchMyProfile

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

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

це більше НЕ повинно бути прийнятою відповіддю, навіть якщо вона була правдою на той час. див. відповідь дивного нижче
bitwit

1
Переповнення стеку не дозволить мені видалити цю застарілу відповідь, оскільки вона прийнята. Відповідь Checkout @ див. Нижче.
Jasarien

196

Натомість, ви пробували використовувати перехід на самому об’єкті таким чином, це дасть вам приємний ефект поступового згасання з одного кольору на інший:

Завдання С

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

Стрімкий

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

Це краще, ніж використання NSTimers, CATextLayers тощо з різних причин. CATextLayer не має належної підтримки для кернінгу тексту або NSAttributedText, а NSTimers відстають (плюс занадто багато коду). Анімація переходу вище робить трюк, а також може бути використана в ланцюговій анімації. У мене була та сама проблема, і я вже пробував наведені вище рішення, але цей простий код творить чудеса.


7
Гарне, елегантне, насправді найкраще та найчистіше рішення.
maksa

17
Чудово. Працює в UIView.transitionWithView(creditsLabel, duration: 0.3, options: .TransitionCrossDissolve, animations: { self.creditsLabel.textColor = UIColor.redColor() }, completion: nil)
Свіфті

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

Мені чомусь не вдається. Це раптово вносить зміни, а не поступово під час анімації. :(
ScottyBlades

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

1
FYI - Перший раз, коли я намагався не працювати, це було тому, що я мав 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

Дякуємо за відповідь @ Strange , яка чудово працює в 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.