有没有办法让UILabel
. 我希望它逐个字符地显示文本值。
帮我解决这个问题
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];
});
这是@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)
}
}
}
}
这可能会更好。
- (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]];
}
我写了一个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;
}
使用演示,我认为您可以根据自己的情况进行一些更改,代码看起来非常非常难看,因为我要去吃晚饭,您可以对其进行专业化。
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)
}
}
}
}
我已经为这个用例编写了一个名为CLTypingLabel的轻量级库,可以在 GitHub 上找到。
它高效、安全且不休眠任何线程。它还提供pause
和continue
接口。随时调用它,它不会中断。
安装 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的示例项目
更新: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
}
}
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()
}
}
UILabel 中没有默认行为来执行此操作,您可以根据计时器一次添加每个字母
我根据第一个答案写了这个:
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
}
}
}
我知道答案为时已晚,但以防万一也有人在 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 }
基于@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()
}
}
}
修改@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)
}
}
对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;
}
我写了一个小的开源库来做到这一点。我使用 NSAttributedString 构建它,这样标签在动画期间不会调整大小。它还支持打字声音和光标动画
在这里查看: