我正在尝试为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,NSViewAnimationFadeInEffect,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.
请告知以上代码有什么问题.
附加说明:
解决方法
我会采取刺:
我在这里发现了几个问题.首先,整个事情被设置为阻塞,所以它将阻塞主线程5秒.这将转换为SPOD /挂起的用户.你可能希望这是非阻塞的,但它需要一些额外的机制来实现这一点.
此外,您正在使用NSAnimationEaSEOut进行淡出效果,这会受到已知错误的影响,导致动画向后运行. (谷歌的“NSAnimationEaSEOut向后”,你可以看到很多人都遇到了这个问题.)我在这个例子的两条曲线中使用了NSAnimationEaseIn.
我使用非阻塞动画制作了一个简单的例子.我不是说这是理想的方法(我发布了第二个答案,可以说更好),但它确实有效,并且可以作为你的起点.这是它的关键:
@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]; } } @end
如果有基于块的API,这将是非常好的…它将节省必须实现此委托对象.
我把整个项目放在GitHub上.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。