在 OS X Yosemite 中对 ViewController 进行动画自定义演示

问题描述 投票:0回答:2

我想实现新方法,我在Google和Stack Overflow上搜索了很多,但没有找到示例。

- (void)presentViewController:(NSViewController *)viewController animator:(id <NSViewControllerPresentationAnimator>)animator

此方法在 OSX 10.10 中可用,此方法需要实现协议

NSViewControllerPresentationAnimator
,该协议有这两个方法

- (void)animatePresentationOfViewController:(NSViewController *)viewController fromViewController:(NSViewController *)fromViewController 

- (void)animateDismissalOfViewController:(NSViewController *)viewController fromViewController:(NSViewController *)fromViewController 

这些方法允许我们在两个 NSViewController 之间进行自定义动画 我需要一个实现的例子,我有这个代码:

- (IBAction)openTask:(id)sender {
    
    NSStoryboard *storyboard = [NSStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
    Tasks *task = [storyboard instantiateControllerWithIdentifier:@"tasks"];
    [self presentViewController:task animator:self];
 
}

- (void)animatePresentationOfViewController:(NSViewController *)viewController
                         fromViewController:(NSViewController *)fromViewController
{
    
    
}

- (void)animateDismissalOfViewController:(NSViewController *)viewController
                      fromViewController:(NSViewController *)fromViewController
{
    
    
}

任何人都可以帮我举例说明如何实现此转变吗?

objective-c macos osx-yosemite
2个回答
16
投票

这是一个简单的版本(Swift),它在新视图控制器的视图中淡入淡出。 我相信你可以将其翻译成 Objective-C。

您将希望实际使用自动布局,而不仅仅是更改框架,但这会使示例更长一些(不是太难。只需在添加视图后添加约束即可)

我不确定您是否也需要视图控制器遏制。然后需要对 addChildViewController 等进行适当的调用。也许有人可以阐明何时需要这样做,或者在任何情况下这是否实际上是良好的做法。

class MyTransitionAnimator: NSObject, NSViewControllerPresentationAnimator {

    func animatePresentationOfViewController(viewController: NSViewController, fromViewController: NSViewController) {

        let bottomVC = fromViewController
        let topVC = viewController

        // make sure the view has a CA layer for smooth animation
        topVC.view.wantsLayer = true

        // set redraw policy
        topVC.view.layerContentsRedrawPolicy = .OnSetNeedsDisplay

        // start out invisible
        topVC.view.alphaValue = 0

        // add view of presented viewcontroller
        bottomVC.view.addSubview(topVC.view)

        // adjust size
        topVC.view.frame = bottomVC.view.frame

        // Do some CoreAnimation stuff to present view
        NSAnimationContext.runAnimationGroup({ (context) -> Void in

            // fade duration
            context.duration = 2
            // animate to alpha 1
            topVC.view.animator().alphaValue = 1

        }, completionHandler: nil)

    }

    func animateDismissalOfViewController(viewController: NSViewController, fromViewController: NSViewController) {

        let bottomVC = fromViewController
        let topVC = viewController

        // make sure the view has a CA layer for smooth animation
        topVC.view.wantsLayer = true

        // set redraw policy
        topVC.view.layerContentsRedrawPolicy = .OnSetNeedsDisplay

        // Do some CoreAnimation stuff to present view
        NSAnimationContext.runAnimationGroup({ (context) -> Void in

            // fade duration
            context.duration = 2
            // animate view to alpha 0
            topVC.view.animator().alphaValue = 0

        }, completionHandler: {

            // remove view
            topVC.view.removeFromSuperview()
        })

    }
}

希望这能让您开始!


0
投票

现在已经是 2023 年了,有一些小的更新。

.OnSetNeedsDisplay
现在是
.onSetNeedsDisplay
(注意大写),并且 animatePresentation 和 animateDismissal 的协议略有不同。

这是托马斯代码的当前版本:

import SwiftUI

class macOSTransitionAnimator: NSObject, NSViewControllerPresentationAnimator {

func animatePresentation(of viewController: NSViewController, from fromViewController: NSViewController) {

    let bottomVC = fromViewController
    let topVC = viewController

    // make sure the view has a CA layer for smooth animation
    topVC.view.wantsLayer = true

    // set redraw policy
    topVC.view.layerContentsRedrawPolicy = .onSetNeedsDisplay

    // start out invisible
    topVC.view.alphaValue = 0

    // add view of presented viewcontroller
    bottomVC.view.addSubview(topVC.view)

    // adjust size
    topVC.view.frame = bottomVC.view.frame

    // Do some CoreAnimation stuff to present view
    NSAnimationContext.runAnimationGroup({ (context) -> Void in

        // fade duration
        context.duration = 2
        // animate to alpha 1
        topVC.view.animator().alphaValue = 1

    }, completionHandler: nil)

}

func animateDismissal(of viewController: NSViewController, from fromViewController: NSViewController) {

    let bottomVC = fromViewController
    let topVC = viewController

    // make sure the view has a CA layer for smooth animation
    topVC.view.wantsLayer = true

    // set redraw policy
    topVC.view.layerContentsRedrawPolicy = .onSetNeedsDisplay

    // Do some CoreAnimation stuff to present view
    NSAnimationContext.runAnimationGroup({ (context) -> Void in

        // fade duration
        context.duration = 2
        // animate view to alpha 0
        topVC.view.animator().alphaValue = 0

    }, completionHandler: {

        // remove view
        topVC.view.removeFromSuperview()
    })

}

}

© www.soinside.com 2019 - 2024. All rights reserved.