Анімувати текст UILabel між двома цифрами?


80

Я новачок у програмуванні iPhone та Mac (розроблений раніше для Windows), і у мене є запитання:

Як я можу анімувати textвластивість UILabelміж двома числами, наприклад, від 5 до 80 у стилі Ease-Out? Чи можна за допомогою CoreAnimation? Я шукаю в Google цілу годину, але не знайшов нічого, що вирішує мою проблему. Що я хочу: анімуйте гроші користувачів за просту гру. Це виглядає не дуже красиво, коли воно просто переходить від 50 до 100 або щось подібне без анімації.

Хтось має ідею, як це зробити?

Дякую!


2
Це старе питання, але Pop (фреймворк анімації Facebook) буде хорошим рішенням. Ви можете безпосередньо анімувати властивість тексту.
jrturton

Відповіді:


160

Ви можете використовувати автоматичні переходи. Це чудово працює:

// Add transition (must be called after myLabel has been displayed)
 CATransition *animation = [CATransition animation];
animation.duration = 1.0;
animation.type = kCATransitionFade;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[myLabel.layer addAnimation:animation forKey:@"changeTextTransition"];

// Change the text
myLabel.text = newText;

Цей код працює, якщо myLabel вже відображається. Якщо не myLabel.layer буде нульовим, а анімація не буде додана до об'єкта.


у Swift 4 це буде:

let animation: CATransition = CATransition()
animation.duration = 1.0
animation.type = kCATransitionFade
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
myLabel.layer.add(animation, forKey: "changeTextTransition")

2
Я спробував це (переконавшись, що шар не дорівнює нулю при додаванні анімації), але текст все одно не анімується. Будь-які інші проблеми?
elsurudo

5
Тільки допоміжна примітка, ви повинні додати анімацію безпосередньо перед тим, як змінювати текст кожного разу, коли ви хочете змінити текст і мати ефект затухання. Однак вам не потрібно кожного разу створювати новий Перехід, один і той самий екземпляр можна використовувати повторно знову і знову.
Lance

2
Питання полягало в тому, як анімувати числа, наприклад, збільшуючи їх у значенні, а не графічно згасаючи між ними. Використання PRTween: github.com/shu223/TweenDemo/tree / ...
jowie

14
На насправді, якщо ви встановите removedOnCompletionна NOна примірнику CATransition, кожна зміна лейблу textбуде анімаційним.
Марк Адамс,

1
@kientux У ключі немає нічого особливого changeTextTransition. Це просто рядок, який ідентифікує анімацію , а це означає, що це рядок, який ви можете використовувати пізніше для ідентифікації анімації, яку ви раніше додали. Якщо вам не потрібно буде ідентифікувати анімацію пізніше, ви можете просто вказати nil.
Ямеск 01.03.17

27

Це добре працює!

Завдання-C

[UIView transitionWithView:self.label 
                  duration:.5f 
                   options:UIViewAnimationOptionCurveEaseInOut | 
                           UIViewAnimationOptionTransitionCrossDissolve 
                animations:^{

    self.label.text = rand() % 2 ? @"111!" : @"42";

} completion:nil];

Стрімкий 2

UIView.transitionWithView(label, duration: 0.25, options: [.CurveEaseInOut, .TransitionCrossDissolve], animations: {
    self.label.text = (arc4random() % 2 == 0) ? "111" : "222"
}, completion: nil)

Стрімкий 3, 4, 5

UIView.transition(with: label, duration: 0.25, options: [.curveEaseInOut, .transitionCrossDissolve], animations: {
    self.label.text = (arc4random() % 2 == 0) ? "111" : "222"
}, completion: nil)

1
Працював також для інших властивостей, таких як зміна imageаUIImageView
SaltyNuts

7

Я знайшов чудовий двигун для вирівнювання значень із різноманітними функціями синхронізації, який називається PRTween . Встановіть класи та створіть код у таких рядках:

- (IBAction)tweenValue
{
    [[PRTween sharedInstance] removeTweenOperation:activeTweenOperation];
    PRTweenPeriod *period = [PRTweenPeriod periodWithStartValue:0.0 endValue:100.0 duration:1.0];
    activeTweenOperation = [[PRTween sharedInstance] addTweenPeriod:period
                                                             target:self
                                                           selector:@selector(update:)
                                                     timingFunction:&PRTweenTimingFunctionCircOut];
}

- (void)update:(PRTweenPeriod*)period
{
    self.animatingView.center = CGPointMake(period.tweenedValue + 100.0, 200.0);
    self.valueLabel.text = [NSString stringWithFormat:@"%.2f", period.tweenedValue];
}

Працює для мене частуванням. :)


5

Якщо ви хочете, щоб він підраховував догори і вниз, коли новий номер відсуває попереднє число (наприклад, галочка або щось інше):

let animation = CATransition()
animation.removedOnCompletion = true
animation.duration = 0.2
animation.type = kCATransitionPush
animation.subtype = newValue > value ? kCATransitionFromTop : kCATransitionFromBottom
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
valueLabel.layer.addAnimation(animation, forKey:"changeTextTransition")

Гей! Дякую за вашу відповідь! Це працює досить акуратно. Я маю лише подальше запитання. Чи знаєте ви, як анімувати лише частини тексту? Як 3-й символ, а решта нехай не зміниться? Я хотів би застосувати мітку, яка показує цифри. Якщо значення змінюється, лише цифри повинні оживляти, це насправді змінилося.
Ларс Петерсен

Особисто я б розглянув питання використання CoreGraphics та CoreAnimation для такого роду речей. Або ви могли б обдурити і нанизати пару ярликів? Залежить від того, наскільки складною є ваша струна.
Адам Уейт,

3

У Swift 2.0, використовуючи UIView.transitionWithView()метод:

UIView.transitionWithView(self.payPeriodSummaryLabel,
        duration: 0.2,
        options: [.CurveEaseInOut, .TransitionCrossDissolve],
        animations: { () -> Void in
            self.label.text = "your text value"
        }, completion: nil)

1

ще одна проста альтернатива

extension UILabel {    
    func countAnimation(upto: Double) {
        let from: Double = text?.replace(string: ",", replacement: ".").components(separatedBy: CharacterSet.init(charactersIn: "-0123456789.").inverted).first.flatMap { Double($0) } ?? 0.0
        let steps: Int = 20
        let duration = 0.350
        let rate = duration / Double(steps)
        let diff = upto - from
        for i in 0...steps {
            DispatchQueue.main.asyncAfter(deadline: .now() + rate * Double(i)) {
                self.text = "\(from + diff * (Double(i) / Double(steps)))"
            }
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.