如何使用动画淡出一个NSView?

33

这个问题应该很简单,但我却找不出错在哪里。我按照指南查看了文档,但还是没能解决它。 我有一个嵌套的视图,其中包含一个 IBAction,它应该使内部视图淡出... 就是这样。下面是代码:

NSViewAnimation *theAnim;
NSMutableDictionary *viewDict;

// Create the attributes dictionary for the view.
viewDict = [NSMutableDictionary dictionaryWithCapacity:2];

// Set the target object to be the view.
[viewDict setObject:_innerView forKey:NSViewAnimationTargetKey];

// Set this view to fade out
[viewDict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];

theAnim = [[NSViewAnimation alloc] initWithViewAnimations:@[viewDict]];

// Set some additional attributes for the animation.
[theAnim setDuration:1.0];

// Run the animation.
[theAnim startAnimation];
我使用NSLog检查了viewDict、theAnim和nil,它们都不是nil。我几乎完全复制了以前的程序,在那个程序中这个功能是正常的,但现在找不出问题所在。
我正在使用Xcode 5.1.1。
3个回答

82

现代方法要简单得多:

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
    context.duration = 1;
    view.animator.alphaValue = 0;
}
completionHandler:^{
    view.hidden = YES;
    view.alphaValue = 1;
}];

如果视图层次结构是支持图层的,实际上只需要这样做:

view.animator.hidden = YES;

7
简述区别,这里使用的是核心动画 Core Animation 技术,但是针对 AppKit 视图中内置可动画属性的动画代理进行调用。而问题提出者则使用了旧版的非核心动画技术,通常更少效率。 - uchuugaka
1
我希望我能给你一千个赞,因为这行代码 view.animator.hidden = YES; 简直太棒了,伙计。 :) - elk_cloner

13

如果你想要 Swift 版本:

NSAnimationContext.runAnimationGroup({ context in
    context.duration = 1
    self.view.animator().alphaValue = 0
}, completionHandler: {
    self.view.isHidden = true
    self.view.alphaValue = 1
})

对于 layer-backed 视图,这已经足够了:

view.animator().isHidden = true

对于那些已经使用Swift 5.3或更高版本的人,您可以利用新的多个尾随闭包语法糖,以获得更加简洁的版本:

NSAnimationContext.runAnimationGroup { context in
    context.duration = 1
    self.view.animator().alphaValue = 0
} completionHandler: {
    self.view.isHidden = true
    self.view.alphaValue = 1
}

1
谢谢,非常有帮助!在开始淡出之前,有没有办法让标签可见2秒钟左右?(我将其用作操作完成后的状态通知) - Cheetaiean

0

成功运行的Swift版本。

// Extension
extension NSViewAnimation {

   public static func make(target: NSView, effect: NSViewAnimation.EffectName) -> NSViewAnimation {
      var animationDict: [NSViewAnimation.Key : Any] = [:]
      animationDict[.target] = target
      animationDict[.effect] = effect
      let viewAnimation = NSViewAnimation(viewAnimations: [animationDict])
      return viewAnimation
   }
}

// Custom subclass of NSView
class MySimpleView: NSView {

   override func draw(_ dirtyRect: NSRect) {
      NSColor.brown.setFill()
      dirtyRect.fill()
   }

   func animateFadeOut() {
      let animation = NSViewAnimation.make(target: self, effect: .fadeOut)
      animation.start()
   }
}

// Usage
let containerView = NSView()
let view = MySimpleView(frame: CGRect(x: 20, y: 20, width: 60, height: 60))
view.autoresizingMask = []
containerView.addSubview(view)

// At some point later
view.animateFadeOut() // Works as expected.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接