App*_*rew 4 cocoa objective-c osx-lion
我正在尝试编写一个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];
}
Run Code Online (Sandbox Code Playgroud)
不用说,但上面的代码根本不起作用.我看到的唯一效果是在同一窗口上闪烁进度条.这可能是因为我试图"动画"它时阻止了主要的runloop.
请告知以上代码有什么问题.
附加说明:
setAnimatedStringValue始终由a调用NSTimer,它被添加到main中NSRunLoop.
在发布上一个答案之后,我有点蠢蠢欲动.我将离开那个答案,因为它与你发布的代码和使用密切相关NSViewAnimation.然而,我确实提出了一个更加简洁,虽然稍微难以阅读(由于块参数缩进)版本NSAnimationContext而是使用.这是'tis:
#import <QuartzCore/QuartzCore.h>
@interface NSTextField (AnimatedSetString)
- (void) setAnimatedStringValue:(NSString *)aString;
@end
@implementation NSTextField (AnimatedSetString)
- (void) setAnimatedStringValue:(NSString *)aString
{
if ([[self stringValue] isEqual: aString])
{
return;
}
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setDuration: 1.0];
[context setTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut]];
[self.animator setAlphaValue: 0.0];
}
completionHandler:^{
[self setStringValue: aString];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setDuration: 1.0];
[context setTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn]];
[self.animator setAlphaValue: 1.0];
} completionHandler: ^{}];
}];
}
@end
Run Code Online (Sandbox Code Playgroud)
注意:要CAMediaTimingFunction使用此API 访问此处用于指定非默认计时功能的类,您需要包含QuartzCore.framework在项目中.
也在GitHub上.
对于斯威夫特3,这里有两个方便的setText()和setAttributedText()从一个文本淡出到另一个扩展方法:
import Cocoa
extension NSTextField {
func setStringValue(_ newValue: String, animated: Bool = true, interval: TimeInterval = 0.7) {
guard stringValue != newValue else { return }
if animated {
animate(change: { self.stringValue = newValue }, interval: interval)
} else {
stringValue = newValue
}
}
func setAttributedStringValue(_ newValue: NSAttributedString, animated: Bool = true, interval: TimeInterval = 0.7) {
guard attributedStringValue != newValue else { return }
if animated {
animate(change: { self.attributedStringValue = newValue }, interval: interval)
}
else {
attributedStringValue = newValue
}
}
private func animate(change: @escaping () -> Void, interval: TimeInterval) {
NSAnimationContext.runAnimationGroup({ context in
context.duration = interval / 2.0
context.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
animator().alphaValue = 0.0
}, completionHandler: {
change()
NSAnimationContext.runAnimationGroup({ context in
context.duration = interval / 2.0
context.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
self.animator().alphaValue = 1.0
}, completionHandler: {})
})
}
}
Run Code Online (Sandbox Code Playgroud)
称他们如下:
var stringTextField: NSTextField
var attributedStringTextField: NSTextField
...
stringTextField.setStringValue("New Text", animated: true)
...
let attributedString = NSMutableAttributedString(string: "New Attributed Text")
attributedString.addAttribute(...)
attributedStringTextField.setAttributedStringValue(attributedString, animated: true)
Run Code Online (Sandbox Code Playgroud)