webentwicklung-frage-antwort-db.com.de

Animieren Sie die Textänderung in UILabel

Ich setze einen neuen Textwert auf UILabel. Derzeit erscheint der neue Text gut. Ich möchte jedoch eine Animation hinzufügen, wenn der neue Text angezeigt wird. Ich frage mich, was ich tun kann, um das Aussehen des neuen Textes zu animieren. 

100
Joo Park

Hier ist der Code, damit dies funktioniert.

[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];
17
Joo Park

Ziel c

Um einen true Cross-Dissolve-Übergang zu erreichen (alte Beschriftung ausblendend , während neue Beschriftung einblendet), möchten Sie nicht, dass sie unsichtbar wird. Dies würde zu ungewolltes Flimmern auch bei unverändertem Text führen.

Verwenden Sie stattdessen diesen Ansatz:

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"

Siehe auch: UILabel-Text zwischen zwei Zahlen animieren?

Demonstration in iOS 10, 9, 8:

 Blank, then 1 to 5 fade transition


Getestet mit Xcode 8.2.1 & 7.1, ObjectiveC unter iOS 10 bis 8.0.

► Um das vollständige Projekt herunterzuladen, suchen Sie nach SO-3073520 in Swift Recipes .

149
SwiftArchitect

Ich frage mich, ob es funktioniert und es funktioniert perfekt!

Ziel c

[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)
147
Anton Gaenko

Schnell 4

Die richtige Methode, um ein UILabel (oder einen beliebigen UIView für diese Angelegenheit) zu blenden, ist die Verwendung eines Core Animation Transition. Dies wird weder flimmern noch schwarz werden, wenn der Inhalt unverändert bleibt.

Eine tragbare und saubere Lösung ist die Verwendung einer Extension in Swift (vorherige Änderung sichtbarer Elemente aufrufen).

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

Aufruf sieht so aus:

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

 Blank, then 1 to 5 fade transition


► Diese Lösung finden Sie auf GitHub und weitere Details zu Swift Recipes .

98
SwiftArchitect

seit iOS4 kann es natürlich mit Blöcken gemacht werden:

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

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

ODER 

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

Dies ist eine C # UIView-Erweiterungsmethode, die auf dem Code von @ SwiftArchitect basiert. Wenn das automatische Layout betroffen ist und Steuerelemente je nach Beschriftungstext verschoben werden müssen, verwendet dieser aufrufende Code die Superviewansicht der Beschriftung als Übergangsansicht anstelle der Beschriftung selbst. Ich fügte einen Lambda-Ausdruck für die Aktion hinzu, um sie stärker einzukapseln.

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

Aufrufcode:

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

Swift 4.2-Lösung (4.0-Antwort nehmen und für das Erstellen neuer Enumerationen aktualisieren)

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"
}
1
Chris

Swift 4.2-Version der obigen SwiftArchitect-Lösung (funktioniert hervorragend):

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

Aufruf:

    // This will fade

aLabel.fadeTransition(0.4)
aLabel.text = "text"
1
winnie-ru

Wenn Sie dies in Swift mit einer Verzögerung tun möchten, versuchen Sie Folgendes:

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

                    })
                }

        })
    }

verwenden der folgenden von @matt erstellten Funktion - 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)
}

was wird dies in Swift 3

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

Je nach Ihrem Geschmack und Ihren Bedürfnissen können Sie einen der drei folgenden Codeausschnitte auswählen, um die Textänderungen Ihrer UILabel mit einer Cross-Dissolve-Animation zu animieren:

1. Verwenden von transition(with:duration:options:animations:completion:)

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        $0.frame.Origin = CGPoint(x: 50, y: 50)
        $0.text = "Bob"
        $0.sizeToFit()
        return $0
    }(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. Verwendung der CATransition-Eigenschaft von CATransition und type

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        $0.frame.Origin = CGPoint(x: 50, y: 50)
        $0.text = "Bob"
        $0.sizeToFit()
        return $0
    }(UILabel())
    let animation: CATransition = {
        $0.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        $0.type = kCATransitionFade
        $0.duration = 1
        return $0
    }(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. Verwenden Sie den Parameter CATransition und add(_:forKey:)key

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        $0.frame.Origin = CGPoint(x: 50, y: 50)
        $0.text = "Bob"
        $0.sizeToFit()
        return $0
    }(UILabel())
    let animation: CATransition = {
        $0.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        $0.duration = 1
        return $0
    }(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
0
Imanou Petit

Die Systemstandardwerte von 0,25 für duration und .curveEaseInEaseOut für timingFunction werden häufig aus Gründen der animationsübergreifenden Konsistenz bevorzugt und können weggelassen werden:

let animation = CATransition()
label.layer.add(animation, forKey: nil)
label.text = "New text"

das ist das gleiche wie das Schreiben:

let animation = CATransition()
animation.duration = 0.25
animation.timingFunction = .curveEaseInEaseOut
label.layer.add(animation, forKey: nil)
label.text = "New text"
0
nobody ever

UILabel-Erweiterungslösung

extension UILabel{
  // created to make the code simpler for future used
  // and still can used fadeTransition 
  func textWithAnimation(text:String,duration:CFTimeInterval){
    fadeTransition(duration)
    self.text = text
  }

  //followed from @Chris and @winnie-ru
  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)
  }
}

Einfach aufgerufene Funktion durch  

uiLabel.textWithAnimation(text: "text you want to replace", duration: 0.2)

Danke für all die Tipps, Jungs. Hoffe, das wird auf lange Sicht helfen

0
Muhammad Asyraf

Es gibt eine weitere Lösung, um dies zu erreichen. Es wurde hier beschrieben. Die Idee ist die Unterklasse UILabel und überschreibt die Funktion action(for:forKey:) auf folgende Weise:

class LabelWithAnimatedText: UILabel {
    override var text: String? {
        didSet {
            self.layer.setValue(self.text, forKey: "text")
        }
    }

    override func action(for layer: CALayer, forKey event: String) -> CAAction? {
        if event == "text" {
            if let action = self.action(for: layer, forKey: "backgroundColor") as? CAAnimation {
                let transition = CATransition()
                transition.type = kCATransitionFade

                //CAMediatiming attributes
                transition.beginTime = action.beginTime
                transition.duration = action.duration
                transition.speed = action.speed
                transition.timeOffset = action.timeOffset
                transition.repeatCount = action.repeatCount
                transition.repeatDuration = action.repeatDuration
                transition.autoreverses = action.autoreverses
                transition.fillMode = action.fillMode

                //CAAnimation attributes
                transition.timingFunction = action.timingFunction
                transition.delegate = action.delegate

                return transition
            }
        }
        return super.action(for: layer, forKey: event)
    }
}

Anwendungsbeispiele:

// do not forget to set the "Custom Class" IB-property to "LabelWithAnimatedText"
// @IBOutlet weak var myLabel: LabelWithAnimatedText!
// ...

UIView.animate(withDuration: 0.5) {
    myLabel.text = "I am animated!"
}
myLabel.text = "I am not animated!"
0
Roman Aliyev