Animate text change in UILabel

后端 未结 14 1215
[愿得一人]
[愿得一人] 2020-11-28 17:56

I\'m setting a new text value to a UILabel. Currently, the new text appears just fine. However, I\'d like to add some animation when the new text appears. I\

相关标签:
14条回答
  • 2020-11-28 18:49

    If you would like to do this in Swift with a delay try this:

    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
    
                        })
                    }
    
            })
        }
    

    using the following function created by @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)
    }
    

    which will become this in Swift 3

    func delay(_ delay:Double, closure:()->()) {
        let when = DispatchTime.now() + delay
        DispatchQueue.main.after(when: when, execute: closure)
    }
    
    0 讨论(0)
  • 2020-11-28 18:50

    With Swift 5, you can choose one of the two following Playground code samples in order to animate your UILabel's text changes with some cross dissolve animation.


    #1. Using UIView's transition(with:duration:options:animations:completion:) class method

    import UIKit
    import PlaygroundSupport
    
    class ViewController: UIViewController {
    
        let label = UILabel()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            label.text = "Car"
    
            view.backgroundColor = .white
            view.addSubview(label)
    
            label.translatesAutoresizingMaskIntoConstraints = false
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
            view.addGestureRecognizer(tapGesture)
        }
    
        @objc func toggle(_ sender: UITapGestureRecognizer) {
            let animation = {
                self.label.text = self.label.text == "Car" ? "Plane" : "Car"
            }
            UIView.transition(with: label, duration: 2, options: .transitionCrossDissolve, animations: animation, completion: nil)
        }
    
    }
    
    let controller = ViewController()
    PlaygroundPage.current.liveView = controller
    

    #2. Using CATransition and CALayer's add(_:forKey:) method

    import UIKit
    import PlaygroundSupport
    
    class ViewController: UIViewController {
    
        let label = UILabel()
        let animation = CATransition()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            label.text = "Car"
    
            animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
            // animation.type = CATransitionType.fade // default is fade
            animation.duration = 2
    
            view.backgroundColor = .white
            view.addSubview(label)
    
            label.translatesAutoresizingMaskIntoConstraints = false
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
            view.addGestureRecognizer(tapGesture)
        }
    
        @objc func toggle(_ sender: UITapGestureRecognizer) {
            label.layer.add(animation, forKey: nil) // The special key kCATransition is automatically used for transition animations
            label.text = label.text == "Car" ? "Plane" : "Car"
        }
    
    }
    
    let controller = ViewController()
    PlaygroundPage.current.liveView = controller
    
    0 讨论(0)
  • 2020-11-28 18:50

    Swift 4.2 solution (taking 4.0 answer and updating for new enums to compile)

    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)
        }
    }
    
    func updateLabel() {
    myLabel.fadeTransition(0.4)
    myLabel.text = "Hello World"
    }
    
    0 讨论(0)
  • 2020-11-28 18:51

    This is a C# UIView extension method that's based on @SwiftArchitect's code. When auto layout is involved and controls need to move depending on the label's text, this calling code uses the Superview of the label as the transition view instead of the label itself. I added a lambda expression for the action to make it more encapsulated.

    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();
    }
    

    Calling code:

      labelSuperview.FadeTransition( 0.5d, () =>
      {
        if ( condition )
          label.Text = "Value 1";
        else
          label.Text = "Value 2";
      } );
    
    0 讨论(0)
  • 2020-11-28 18:54

    I wonder if it works, and it works perfectly!

    Objective-C

    [UIView transitionWithView:self.label 
                      duration:0.25f 
                       options:UIViewAnimationOptionTransitionCrossDissolve 
                    animations:^{
    
        self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!";
    
      } completion:nil];
    

    Swift 3, 4, 5

    UIView.transition(with: label,
                  duration: 0.25,
                   options: .transitionCrossDissolve,
                animations: { [weak self] in
                    self?.label.text = (arc4random()() % 2 == 0) ? "One" : "Two"
             }, completion: nil)
    
    0 讨论(0)
  • 2020-11-28 18:56

    Objective-C

    To achieve a true cross-dissolve transition (old label fading out while new label fading in), you don't want fade to invisible. It would result in unwanted flicker even if text is unchanged.

    Use this approach instead:

    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"
    

    Also see: Animate UILabel text between two numbers?

    Demonstration in iOS 10, 9, 8:


    Tested with Xcode 8.2.1 & 7.1, ObjectiveC on iOS 10 to 8.0.

    ► To download the full project, search for SO-3073520 in Swift Recipes.

    0 讨论(0)
提交回复
热议问题