首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在更改文本时,如何在fadeIn fadeOut中动画化NSTextField效果?

在更改文本时,如何在fadeIn fadeOut中动画化NSTextField效果?
EN

Stack Overflow用户
提问于 2013-01-05 18:26:30
回答 3查看 3.8K关注 0票数 4

我试图为NSTextField编写一个类别,它将添加一个新的方法setAnimatedStringValue。这个方法应该很好地淡出当前文本,然后设置新文本,然后淡入。

以下是我的实施情况:

代码语言:javascript
复制
- (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];
}

不用说,但是上面的代码根本不起作用。我看到的唯一效果是同一窗口上一个进度条的闪烁。这可能是因为我在试图“动画”它的时候阻塞了主运行循环。

请建议上述代码有什么问题。

附加说明:

setAnimatedStringValue总是由添加到主NSRunLoop中的NSTimer调用。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-01-06 15:58:50

我试试看:

我在这里发现了一些问题。首先,整件事情被设置为阻塞,所以它将阻塞主线程5秒。这将以SPOD/hang的形式转换给用户。你可能希望这是非阻塞,但它将需要一些额外的机器来实现这一点。

另外,您正在使用NSAnimationEaseOut作为淡出效果,这是由一个已知的bug影响的,它会导致动画向后运行。(在谷歌上搜索"NSAnimationEaseOut向后“,你可以看到很多人都遇到了这个问题。)在这个例子中,我对这两条曲线都使用了NSAnimationEaseIn

我把它作为一个简单的非阻塞动画的例子。我不打算说这是理想的方法(我发布了第二个答案,可以说更好),但它是有效的,并有望成为你的起点。关键在于:

代码语言:javascript
复制
@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上。

票数 1
EN

Stack Overflow用户

发布于 2013-01-06 16:28:00

在贴出之前的答案后,我四处打听了一下。我之所以留下这个答案,是因为它与您发布的代码非常对应,并且使用NSViewAnimation。然而,我确实想出了一个更加简洁的版本,尽管阅读起来有点困难(因为块参数缩进),而不是使用NSAnimationContext。这是:

代码语言:javascript
复制
#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

注意:为了访问这里使用的用于指定非默认计时函数的CAMediaTimingFunction类,需要在项目中包含QuartzCore.framework

也在GitHub上。

票数 9
EN

Stack Overflow用户

发布于 2017-05-12 21:36:01

对于Swift 3,下面是两个方便的setText()setAttributedText()扩展方法,它们从一个文本淡出到另一个文本:

代码语言:javascript
复制
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: {})
        })
    }
}

请按以下方式称呼他们:

代码语言:javascript
复制
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)
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14174911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档