本文介绍了如何在NSTextField中改变文本时对fadeIn fadeOut效果进行动画处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我试图为 NSTextField 写一个类别,它会添加一个新方法 setAnimatedStringValue 。这个方法应该很好地淡出当前文本,然后设置新的文本,然后淡入。 下面是我的实现: - - (void)setAnimatedStringValue:(NSString *)aString { if([[self stringValue] isEqualToString:aString] ){ return; } NSMutableDictionary * dict = Nil; NSViewAnimation * fadeOutAnim; dict = [NSDictionary dictionaryWithObjectsAndKeys:self,NSViewAnimationTargetKey, NSViewAnimationFadeOutEffect,NSViewAnimationEffectKey,nil] fadeOutAnim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects: dict,nil]]; [fadeOutAnim setDuration:2]; [fadeOutAnim setAnimationCurve:NSAnimationEaseOut]; [fadeOutAnim setAnimationBlockingMode:NSAnimationBlocking]; NSViewAnimation * fadeInAnim; dict = [NSDictionary dictionaryWithObjectsAndKeys:self,NSViewAnimationTargetKey, NSViewAnimationFadeInEffect,NSViewAnimationEffectKey,nil]; fadeInAnim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects: dict,nil]]; [fadeInAnim setDuration:3]; [fadeInAnim setAnimationCurve:NSAnimationEaseIn]; [fadeInAnim setAnimationBlockingMode:NSAnimationBlocking]; [fadeOutAnim startAnimation]; [self setStringValue:aString]; [fadeInAnim startAnimation]; } 不用说,但上述代码根本不工作。我看到的唯一效果是在同一个窗口上进度条的闪烁。这可能是因为我在阻止主runloop尝试动画它。 请建议上面的代码有什么问题。 其他附注: setAnimatedStringValue 由 NSTimer 添加到 NSRunLoop 。解决方案我会尝试一下: 我在这里发现了一些问题。首先,这整个事情被设置为阻塞,因此它将阻塞主线程5秒钟。这将转换为用户作为SPOD /挂起。你可能希望这是非阻塞,但它需要一点点额外的机械,使这种情况发生。 此外,您使用 NSAnimationEaseOut 获得淡出效果,这是由已知的错误导致动画向后运行。 (Google forNSAnimationEaseOut backwards,您可以看到很多都遇到了这个问题。)我使用 NSAnimationEaseIn 为这个例子的两个曲线。 / p> 我得到这个工作与一个微不足道的例子与非阻塞动画。我不会说这是理想方法(我发布了第二个答案,可以说更好),但它的工作,并希望可以作为一个跳跃点为你。这里是它的关键: @interface NSTextField(AnimatedSetString) - (void)setAnimatedStringValue: (NSString *)aString; @end @interface SOTextFieldAnimationDelegate:NSObject< NSAnimationDelegate> - (id)initForSettingString:(NSString *)newString onTextField:(NSTextField *)tf; @end @implementation NSTextField(AnimatedSetString) - (void)setAnimatedStringValue:(NSString *)aString { if([[self stringValue] isEqual:aString]) { return; } [[[SOTextFieldAnimationDelegate alloc] initForSettingString:aString onTextField:self] autorelease]; } @end @implementation SOTextFieldAnimationDelegate { NSString * _newString; NSAnimation * _fadeIn; NSAnimation * _fadeOut; NSTextField * _tf; } - (id)initForSettingString:(NSString *)newString onTextField:(NSTextField *)tf { if(self = [super init]) { _newString = [newString copy]; _tf = [tf retain]; [self retain]; //当动画完成时,我们将自动释放自己。 _fadeOut = [[NSViewAnimation alloc] initWithViewAnimations:@ [(@ { NSViewAnimationTargetKey:tf, NSViewAnimationEffectKey:NSViewAnimationFadeOutEffect})]]; [_fadeOut setDuration:2]; [_fadeOut setAnimationCurve:NSAnimationEaseIn]; [_fadeOut setAnimationBlockingMode:NSAnimationNonblocking]; _fadeOut.delegate = self; _fadeIn = [[NSViewAnimation alloc] initWithViewAnimations:@ [(@ { NSViewAnimationTargetKey:tf, NSViewAnimationEffectKey:NSViewAnimationFadeInEffect})]]; [_fadeIn setDuration:3]; [_fadeIn setAnimationCurve:NSAnimationEaseIn]; [_fadeInsetAnimationBlockingMode:NSAnimationNonblocking]; [_fadeOut startAnimation]; } return self; } - (void)dealloc { [_newString release]; [_tf release]; [_fadeOut release]; [_fadeIn release]; [super dealloc] } - (void)animationDidEnd:(NSAnimation *)animation { if(_fadeOut == animation) { _fadeOut .delegate = nil; [_fadeOut release]; _fadeOut = nil; _tf.hidden = YES; [_tf setStringValue:_newString]; _fadeIn.delegate = self; [_fadeIn startAnimation]; } else { _fadeIn.delegate = nil; [_fadeIn release]; _fadeIn = nil; [self autorelease]; } } @end 如果有基于块的API为这...它会节省必须实现这个委托对象真的很好。 我把整个项目放在 GitHub 。 I am trying to write a category for NSTextField which will add a new method setAnimatedStringValue. This method is supposed to nicely fade-out the current text, then set the new text and then fade that in.Below is my implementation:-- (void) setAnimatedStringValue:(NSString *)aString { if ([[self stringValue] isEqualToString:aString]) { return; } NSMutableDictionary *dict = Nil; NSViewAnimation *fadeOutAnim; dict = [NSDictionary dictionaryWithObjectsAndKeys:self, NSViewAnimationTargetKey, NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey, nil]; fadeOutAnim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects: dict, nil]]; [fadeOutAnim setDuration:2]; [fadeOutAnim setAnimationCurve:NSAnimationEaseOut]; [fadeOutAnim setAnimationBlockingMode:NSAnimationBlocking]; NSViewAnimation *fadeInAnim; dict = [NSDictionary dictionaryWithObjectsAndKeys:self, NSViewAnimationTargetKey, NSViewAnimationFadeInEffect, NSViewAnimationEffectKey, nil]; fadeInAnim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects: dict, nil]]; [fadeInAnim setDuration:3]; [fadeInAnim setAnimationCurve:NSAnimationEaseIn]; [fadeInAnim setAnimationBlockingMode:NSAnimationBlocking]; [fadeOutAnim startAnimation]; [self setStringValue:aString]; [fadeInAnim startAnimation];}Needless to say, but the above code does not work at all. The only effect I see is the flickering of a progress bar on the same window. That is possibly because I am blocking the main runloop while trying to "animate" it.Please suggest what is wrong with the above code.Additional note:setAnimatedStringValue is always invoked by a NSTimer, which is added to the main NSRunLoop. 解决方案 I'll take a stab:I found a couple problems here. First off, this whole thing is set up to be blocking, so it's going to block the main thread for 5 seconds. This will translate to the user as a SPOD/hang. You probably want this to be non-blocking, but it'll require a little bit of extra machinery to make that happen.Also, you're using NSAnimationEaseOut for the fade out effect, which is effected by a known bug where it causes the animation to run backwards. (Google for "NSAnimationEaseOut backwards" and you can see that many have hit this problem.) I used NSAnimationEaseIn for both curves for this example.I got this working for a trivial example with non-blocking animations. I'm not going to say that this is the ideal approach (I posted a second answer that arguably better), but it works, and can hopefully serve as a jumping off point for you. Here's the crux of it:@interface NSTextField (AnimatedSetString)- (void) setAnimatedStringValue:(NSString *)aString;@end@interface SOTextFieldAnimationDelegate : NSObject <NSAnimationDelegate>- (id)initForSettingString: (NSString*)newString onTextField: (NSTextField*)tf;@end@implementation NSTextField (AnimatedSetString)- (void) setAnimatedStringValue:(NSString *)aString{ if ([[self stringValue] isEqual: aString]) { return; } [[[SOTextFieldAnimationDelegate alloc] initForSettingString: aString onTextField: self] autorelease];}@end@implementation SOTextFieldAnimationDelegate{ NSString* _newString; NSAnimation* _fadeIn; NSAnimation* _fadeOut; NSTextField* _tf;}- (id)initForSettingString: (NSString*)newString onTextField: (NSTextField*)tf{ if (self = [super init]) { _newString = [newString copy]; _tf = [tf retain]; [self retain]; // we'll autorelease ourselves when the animations are done. _fadeOut = [[NSViewAnimation alloc] initWithViewAnimations: @[ (@{ NSViewAnimationTargetKey : tf , NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect})] ]; [_fadeOut setDuration:2]; [_fadeOut setAnimationCurve: NSAnimationEaseIn]; [_fadeOut setAnimationBlockingMode:NSAnimationNonblocking]; _fadeOut.delegate = self; _fadeIn = [[NSViewAnimation alloc] initWithViewAnimations: @[ (@{ NSViewAnimationTargetKey : tf , NSViewAnimationEffectKey : NSViewAnimationFadeInEffect})] ]; [_fadeIn setDuration:3]; [_fadeIn setAnimationCurve:NSAnimationEaseIn]; [_fadeIn setAnimationBlockingMode:NSAnimationNonblocking]; [_fadeOut startAnimation]; } return self;}- (void)dealloc{ [_newString release]; [_tf release]; [_fadeOut release]; [_fadeIn release]; [super dealloc];}- (void)animationDidEnd:(NSAnimation*)animation{ if (_fadeOut == animation) { _fadeOut.delegate = nil; [_fadeOut release]; _fadeOut = nil; _tf.hidden = YES; [_tf setStringValue: _newString]; _fadeIn.delegate = self; [_fadeIn startAnimation]; } else { _fadeIn.delegate = nil; [_fadeIn release]; _fadeIn = nil; [self autorelease]; }}@endIt would be really nice if there were block-based API for this... it'd save having to implement this delegate object.I put the whole project up on GitHub. 这篇关于如何在NSTextField中改变文本时对fadeIn fadeOut效果进行动画处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 07-31 01:50