如何在更改文本时在NSTextField中为fadeIn fadeOut效果设置动画?

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.

ipm*_*mcc 9

在发布上一个答案之后,我有点蠢蠢欲动.我将离开那个答案,因为它与你发布的代码和使用密切相关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上.


Lar*_*erg 6

对于斯威夫特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)