30

有没有办法让UILabel. 我希望它逐个字符地显示文本值。

帮我解决这个问题

4

15 回答 15

64

2018 年更新,Swift 4.1:

extension UILabel {

    func animate(newText: String, characterDelay: TimeInterval) {

        DispatchQueue.main.async {

            self.text = ""

            for (index, character) in newText.enumerated() {
                DispatchQueue.main.asyncAfter(deadline: .now() + characterDelay * Double(index)) {
                    self.text?.append(character)
                }
            }
        }
    }

}

调用它很简单并且线程安全:

myLabel.animate(newText: myLabel.text ?? "May the source be with you", characterDelay: 0.3)

@objC,2012:

试试这个原型函数:

- (void)animateLabelShowText:(NSString*)newText characterDelay:(NSTimeInterval)delay
{    
    [self.myLabel setText:@""];

    for (int i=0; i<newText.length; i++)
    {
        dispatch_async(dispatch_get_main_queue(),
        ^{
            [self.myLabel setText:[NSString stringWithFormat:@"%@%C", self.myLabel.text, [newText characterAtIndex:i]]];
        });

        [NSThread sleepForTimeInterval:delay];
    }
}

并以这种方式调用它:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
    [self animateLabelShowText:@"Hello Vignesh Kumar!" characterDelay:0.5];
});
于 2012-07-27T12:12:29.770 回答
9

这是@Andrei G. 作为 Swift 扩展的答案:

extension UILabel {

    func setTextWithTypeAnimation(typedText: String, characterInterval: NSTimeInterval = 0.25) {
        text = ""
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)) {
            for character in typedText.characters {
                dispatch_async(dispatch_get_main_queue()) {
                    self.text = self.text! + String(character)
                }
                NSThread.sleepForTimeInterval(characterInterval)
            }
        }
    }

}
于 2015-06-19T23:27:43.860 回答
7

这可能会更好。

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *string =@"Risa Kasumi & Yuma Asami";

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:string forKey:@"string"];
    [dict setObject:@0 forKey:@"currentCount"];
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(typingLabel:) userInfo:dict repeats:YES];
    [timer fire];


}

-(void)typingLabel:(NSTimer*)theTimer
{
    NSString *theString = [theTimer.userInfo objectForKey:@"string"];
    int currentCount = [[theTimer.userInfo objectForKey:@"currentCount"] intValue];
    currentCount ++;
    NSLog(@"%@", [theString substringToIndex:currentCount]);

    [theTimer.userInfo setObject:[NSNumber numberWithInt:currentCount] forKey:@"currentCount"];

     if (currentCount > theString.length-1) {
        [theTimer invalidate];
    }

    [self.label setText:[theString substringToIndex:currentCount]];
}
于 2013-02-20T18:29:14.280 回答
4

我写了一个demo,可以用,支持ios 3.2及以上

在你的 .m 文件中

- (void)displayLabelText
{

    i--;
    if(i<0)
    {
        [timer invalidate];
    }
    else
    {
        [label setText:[NSString stringWithFormat:@"%@",[text substringToIndex:(text.length-i-1)]]];
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 60)];
    [label setBackgroundColor:[UIColor redColor]];
    text = @"12345678";
    [label setText:text];
    [self.view addSubview:label];
    i=label.text.length;
    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(displayLabelText) userInfo:nil repeats:YES];
    [timer fire];    
}

在你的 .h 文件中

@interface labeltextTestViewController : UIViewController {
    UILabel *label;
    NSTimer *timer;
    NSInteger i;
    NSString *text;
}

使用演示,我认为您可以根据自己的情况进行一些更改,代码看起来非常非常难看,因为我要去吃晚饭,您可以对其进行专业化。

于 2012-07-27T12:22:05.640 回答
4

Swift 3,仍然归功于 Andrei G. 的概念。

extension UILabel{

func setTextWithTypeAnimation(typedText: String, characterInterval: TimeInterval = 0.25) {
    text = ""
    DispatchQueue.global(qos: .userInteractive).async {

        for character in typedText.characters {
            DispatchQueue.main.async {
                self.text = self.text! + String(character)
            }
            Thread.sleep(forTimeInterval: characterInterval)
        }

    }
}

}
于 2016-11-29T10:52:35.987 回答
3

我已经为这个用例编写了一个名为CLTypingLabel的轻量级库,可以在 GitHub 上找到。

它高效、安全且不休眠任何线程。它还提供pausecontinue接口。随时调用它,它不会中断。

安装 CocoaPods 后,在 Podfile 中添加如下内容以使用它:

pod 'CLTypingLabel'

示例代码

将标签的类从 UILabel 更改为 CLTypingLabel; 在此处输入图像描述

@IBOutlet weak var myTypeWriterLabel: CLTypingLabel!

在运行时,设置标签的文本会自动触发动画:

myTypeWriterLabel.text = "This is a demo of typing label animation..."

您可以自定义每个字符之间的时间间隔:

myTypeWriterLabel.charInterval = 0.08 //optional, default is 0.1

您可以随时暂停打字动画:

myTypeWriterLabel.pauseTyping() //this will pause the typing animation
myTypeWriterLabel.continueTyping() //this will continue paused typing animation

还有一个带有cocoapods的示例项目

于 2016-02-21T22:28:15.587 回答
2

更新:2019 年,斯威夫特 5

有用!只需复制粘贴我的答案并查看您的结果

@IBOutlet weak var titleLabel: UILabel!还要在 viewDidLoad() 之前创建一个

override func viewDidLoad() {
    super.viewDidLoad()

    titleLabel.text = ""
    let titleText = "⚡️Please Vote my answer"
    var charIndex = 0.0
    for letter in titleText {
        Timer.scheduledTimer(withTimeInterval: 0.1 * charIndex, repeats: false) { (timer) in
            self.titleLabel.text?.append(letter)
        }
         charIndex += 1
    }

   }
于 2019-12-24T04:26:35.940 回答
2

SwiftUI + 组合示例:

struct TypingText: View {
    typealias ConnectablePublisher = Publishers.Autoconnect<Timer.TimerPublisher>
    private let text: String
    private let timer: ConnectablePublisher
    private let alignment: Alignment

    @State private var visibleChars: Int = 0

    var body: some View {
        ZStack(alignment: self.alignment) {
            Text(self.text).hidden() // fixes the alignment in position
            Text(String(self.text.dropLast(text.count - visibleChars))).onReceive(timer) { _ in
                if self.visibleChars < self.text.count {
                    self.visibleChars += 1
                }
            }
        }
    }

    init(text: String) {
        self.init(text: text, typeInterval: 0.05, alignment: .leading)
    }

    init(text: String, typeInterval: TimeInterval, alignment: Alignment) {
        self.text = text
        self.alignment = alignment
        self.timer = Timer.TimerPublisher(interval: typeInterval, runLoop: .main, mode: .common).autoconnect()
    }
}
于 2019-12-31T14:59:18.243 回答
1

UILabel 中没有默认行为来执行此操作,您可以根据计时器一次添加每个字母

于 2012-07-27T11:36:18.623 回答
1

我根据第一个答案写了这个:

import Foundation

var stopAnimation = false

extension UILabel {

    func letterAnimation(newText: NSString?, completion: (finished : Bool) -> Void) {
        self.text = ""
        if !stopAnimation {
            dispatch_async(dispatch_queue_create("backroundQ", nil)) {
                if var text = newText {
                    text = (text as String) + " "

                    for(var i = 0; i < text.length;i++){
                        if stopAnimation {
                            break
                        }

                        dispatch_async(dispatch_get_main_queue()) {
                            let range = NSMakeRange(0,i)
                            self.text = text.substringWithRange(range)
                        }

                        NSThread.sleepForTimeInterval(0.05)
                    }
                    completion(finished: true)
                }
            }
            self.text = newText as? String
        }
    }
}
于 2015-10-19T09:02:31.850 回答
1

我知道答案为时已晚,但以防万一也有人在 UITextView 中寻找打字动画。我为 Swift 4 编写了一个小型库Github。您可以在动画完成时设置回调。

@IBOutlet weak var textview:TypingLetterUITextView!
textview.typeText(message, typingSpeedPerChar: 0.1, completeCallback:{
       // complete action after finished typing }

另外,我有用于输入动画的 UILabel 扩展。

label.typeText(message, typingSpeedPerChar: 0.1, didResetContent = true, completeCallback:{
       // complete action after finished typing }
于 2017-11-24T01:15:20.353 回答
0

基于@Adam Waite 的回答。如果有人想将其与完成闭包一起使用。

    func setTextWithTypeAnimation(typedText: String, characterInterval: NSTimeInterval = 0.05, completion: () ->()) {
    text = ""
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)) {
        for character in typedText.characters {
            dispatch_async(dispatch_get_main_queue()) {
                self.text = self.text! + String(character)
            }
            NSThread.sleepForTimeInterval(characterInterval)
        }

        dispatch_async(dispatch_get_main_queue()) {
            completion()
        }
    }
}
于 2016-02-06T16:13:08.740 回答
0

修改@Adam Waite 的代码(干得好,顺便说一句)以逐字显示文本:

    func setTextWithWordTypeAnimation(typedText: String, characterInterval: NSTimeInterval = 0.25) {
    text = ""
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)) {
        let wordArray = typedText.componentsSeparatedByString(" ")
        for word in wordArray {
            dispatch_async(dispatch_get_main_queue()) {
                self.text = self.text! + word + " "
            }
            NSThread.sleepForTimeInterval(characterInterval)
        }
    }
于 2016-04-14T16:25:14.090 回答
0

对Andrei提供的答案进行了一点改进,而不是阻塞主线程。

- (void)animateLabelShowText:(NSString*)newText characterDelay:(NSTimeInterval)delay
{
  [super setText:@""];

  NSTimeInterval appliedDelay = delay;

  for (int i=0; i<newText.length; i++)
  {    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, appliedDelay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [super setText:[NSString stringWithFormat:@"%@%c", self.text, [newText characterAtIndex:i]]];
    });

    appliedDelay += delay;

}
于 2016-07-19T13:08:03.153 回答
0

我写了一个小的开源库来做到这一点。我使用 NSAttributedString 构建它,这样标签在动画期间不会调整大小。它还支持打字声音和光标动画

在这里查看:

https://github.com/ansonyao/AYTypeWriter

于 2018-10-05T06:15:53.577 回答