Анимировать изменение текста в UILabel

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

10 ответов


С

достижения правда переход крест-растворения (старая метка исчезает пока новый ярлык увядая внутри), вы не хотите увядать к невидимому. Это приведет к нежелательное мерцание, даже если текст не изменился.

вместо этого используйте этот подход:

CATransition *animation = [CATransition animation];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = kCATransitionFade;
animation.duration = 0.75;
[aLabel.layer addAnimation:animation forKey:@"kCATransitionFade"];

// This will fade:
aLabel.text = "New"

Также см.: анимировать текст UILabel между двумя числами?

демонстрация в iOS 10, 9, 8:

Blank, then 1 to 5 fade transition


протестировано с Xcode 8.2.1 & 7.1, объективчик on iOS 10 до 8.0.

► скачать полный проект для поиска SO-3073520 на Swift Рецепты.


интересно, работает ли он, и он работает отлично!

С

[UIView transitionWithView:self.label 
                  duration:0.25f 
                   options:UIViewAnimationOptionTransitionCrossDissolve 
                animations:^{

    self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!";

  } completion:nil];

Swift 3

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

Swift 4

правильный способ выцветания UILabel (или любого UIView, если на то пошло) - использовать Core Animation Transition. Это не будет мерцать, и он не будет исчезать до черного цвета, если содержание не изменилось.

портативное и чистое решение использовать Extension в Swift (вызовите предыдущие изменения видимых элементов)

// Usage: insert view.fadeTransition right before changing content
extension UIView {
    func fadeTransition(_ duration:CFTimeInterval) {
        let animation = CATransition()
        animation.timingFunction = CAMediaTimingFunction(name:
            kCAMediaTimingFunctionEaseInEaseOut)
        animation.type = kCATransitionFade
        animation.duration = duration
        layer.add(animation, forKey: kCATransitionFade)
    }
}

ссылка выглядит так:

// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"

Blank, then 1 to 5 fade transition


► найдите это решение на GitHub и дополнительные сведения о Swift Рецепты.


поскольку iOS4 это, очевидно, можно сделать с блоками:

[UIView animateWithDuration:1.0
                 animations:^{
                     label.alpha = 0.0f;
                     label.text = newText;
                     label.alpha = 1.0f;
                 }];

вот код, чтобы сделать эту работу.

[UIView beginAnimations:@"animateText" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1.0f];
[self.lbl setAlpha:0];
[self.lbl setText:@"New Text";
[self.lbl setAlpha:1];
[UIView commitAnimations];

Swift 2.0:

UIView.transitionWithView(self.view, duration: 1.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
    self.sampleLabel.text = "Animation Fade1"
    }, completion: { (finished: Bool) -> () in
        self.sampleLabel.text = "Animation Fade - 34"
})

или

UIView.animateWithDuration(0.2, animations: {
    self.sampleLabel.alpha = 1
}, completion: {
    (value: Bool) in
    self.sampleLabel.alpha = 0.2
})

это метод расширения C# UIView, основанный на коде @SwiftArchitect. Когда используется автоматический макет и элементы управления должны перемещаться в зависимости от текста метки, этот вызывающий код использует Супервизор метки в качестве представления перехода вместо самой метки. Я добавил лямбда-выражение для действия, чтобы сделать его более герметично.

public static void FadeTransition( this UIView AView, double ADuration, Action AAction )
{
  CATransition transition = new CATransition();

  transition.Duration = ADuration;
  transition.TimingFunction = CAMediaTimingFunction.FromName( CAMediaTimingFunction.Linear );
  transition.Type = CATransition.TransitionFade;

  AView.Layer.AddAnimation( transition, transition.Type );
  AAction();
}

телефонный код:

  labelSuperview.FadeTransition( 0.5d, () =>
  {
    if ( condition )
      label.Text = "Value 1";
    else
      label.Text = "Value 2";
  } );

если вы хотите сделать это в Swift С задержкой попробуйте это:

delay(1.0) {
        UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: {
            self.yourLabel.text = "2"
            }, completion:  { finished in

                self.delay(1.0) {
                    UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: {
                        self.yourLabel.text = "1"
                        }, completion:  { finished in

                    })
                }

        })
    }

используя следующую функцию, созданную @matt -https://stackoverflow.com/a/24318861/1982051:

func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

который станет этим в Swift 3

func delay(_ delay:Double, closure:()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.after(when: when, execute: closure)
}

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

1. Используя transition(with:duration:options:animations:completion:)

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        .frame.origin = CGPoint(x: 50, y: 50)
        .text = "Bob"
        .sizeToFit()
        return 
    }(UILabel())

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white
        view.addSubview(label)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
        view.addGestureRecognizer(tapGesture)
    }

    func toggle(_ sender: UITapGestureRecognizer) {
        let animation = {
            self.label.text = self.label.text == "Bob" ? "Dan" : "Bob"
        }
        UIView.transition(with: label, duration: 1, options: .transitionCrossDissolve, animations: animation, completion: nil)
    }

}

let controller = ViewController()
PlaygroundPage.current.liveView = controller

2. Используя CATransition и CATransition ' s type свойства

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        .frame.origin = CGPoint(x: 50, y: 50)
        .text = "Bob"
        .sizeToFit()
        return 
    }(UILabel())
    let animation: CATransition = {
        .timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        .type = kCATransitionFade
        .duration = 1
        return 
    }(CATransition())

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        view.addSubview(label)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
        view.addGestureRecognizer(tapGesture)
    }

    func toggle(_ sender: UITapGestureRecognizer) {
        label.layer.add(animation, forKey: nil)
        label.text = label.text == "Bob" ? "Dan" : "Bob"
        label.sizeToFit()
    }

}

let controller = ViewController()
PlaygroundPage.current.liveView = controller

3. Используя CATransition и add(_:forKey:) key параметр

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        .frame.origin = CGPoint(x: 50, y: 50)
        .text = "Bob"
        .sizeToFit()
        return 
    }(UILabel())
    let animation: CATransition = {
        .timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        .duration = 1
        return 
    }(CATransition())

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white
        view.addSubview(label)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
        view.addGestureRecognizer(tapGesture)
    }

    func toggle(_ sender: UITapGestureRecognizer) {
        label.layer.add(animation, forKey: kCATransitionFade)
        label.text = label.text == "Bob" ? "Dan" : "Bob"
        label.sizeToFit()
    }

}

let controller = ViewController()
PlaygroundPage.current.liveView = controller

Swift 4.2 версия решения SwiftArchitect выше (отлично работает):

    // Usage: insert view.fadeTransition right before changing content    

extension UIView {

        func fadeTransition(_ duration:CFTimeInterval) {
            let animation = CATransition()
            animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
            animation.type = CATransitionType.fade
            animation.duration = duration
            layer.add(animation, forKey: CATransitionType.fade.rawValue)
        }
    }

ссылка:

    // This will fade

aLabel.fadeTransition(0.4)
aLabel.text = "text"