MacOS开发-带有动画的窗口内容切换

MacOS开发-带有动画的窗口内容切换

1.切换窗口内容效果

根据需求,窗口内容需要切换,且要求带有动画效果。实现效果如下图所示:

MacOS开发-带有动画的窗口内容切换

2.实现

思路:程序只有一个window,通过在window的contentview上添加和移除子视图实现页面内容切换,添加动画效果,使之具有视觉切换过程。

2.1 mainMenu.xib部分

在mainMenu.xib中拖入NSView,与窗口通大小,然后在AppDelegate中添加IBOutlet属性,此处我们将该view命名为windowBackView。

MacOS开发-带有动画的窗口内容切换

在windowBackView上添加按钮,并将IBAction拖入AppDelegate.m, 按钮动作名为

- (IBAction)showViewController1:(id)sender;

2.2 新建ViewController类

新建ViewController类,继承自NSViewController。

MacOS开发-带有动画的窗口内容切换

添加控件,以示区别。

2.3 代码部分

在AppDelegate.m中添加属性如下:

@interface AppDelegate ()<ViewControllerDelegate> {
    
    ViewController *_viewController;
}

@property (weak) IBOutlet NSView *windowBackView;
@property (weak) IBOutlet NSWindow *window;

@end

applicationDidFinishLaunching:(NSNotification *)aNotification方法中,添加如下代码

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    
    self.window.contentView.wantsLayer = YES;
    self.window.contentView.layer.backgroundColor = [[NSColor blueColor] CGColor];
    
    _viewController = [[ViewController alloc] initWithDelegate:self];
    _viewController.delegate = self;//设置代理,返回按钮使用
}

实现按钮点击切换内容方法- (IBAction)showViewController1:(id)sender

- (IBAction)showViewController1:(id)sender {
    //控制main Window中页面动画退出
    NSRect windowFrame = [self.window contentView].frame;
    NSRect rect = NSMakeRect(-windowFrame.size.width, 0, windowFrame.size.width, windowFrame.size.height);
    [self moveAnimationWithView:self.windowBackView location:rect];
    
    //控制viewController的view页面进入
    NSRect viewFrame = NSMakeRect(windowFrame.size.width, 0, windowFrame.size.width, windowFrame.size.height);
    [[self.window contentView] addSubview:_viewController.view];
    [_viewController.view setFrame:viewFrame];
    [self moveAnimationWithView:_viewController.view location:windowFrame];
}

其中,- (void)moveAnimationWithView:(NSView *)view location:(NSRect)rect方法如下:

/**
 * @brief 对view执行frame方面的动画,从原始位置移动到rect
 * @param view 需要被执行动画的view
 * @param rect view动画结束后的rect
 */
- (void)moveAnimationWithView:(NSView *)view location:(NSRect)rect{
    [[NSAnimationContext currentContext] setDuration:0.75];
    [[view animator] setFrame:rect];
    [NSAnimationContext endGrouping];
}

Viewcontroller中返回按钮执行动作,通过动画方式移除Viewcontroller的view。Viewcontroller.m中代码如下:

- (instancetype)init {
    return [self initWithDelegate:nil];
}

- (instancetype)initWithDelegate:(id)delegate {
    if (self = [super initWithNibName:@"ViewController" bundle:nil]){
        _delegate = delegate;
        self.view.wantsLayer = YES;
        [self.view.layer setBackgroundColor:[[NSColor cyanColor] CGColor]];
    }
    return self;
}



- (IBAction)backAction:(id)sender {
    if (self.delegate != nil && [self.delegate respondsToSelector:@selector(viewControllerWillClose:)]) {
        [self.delegate viewControllerWillClose:self];
    }
}

在AppDelegate.m中实现返回按钮点击的代理方法:

#pragma mark - ViewController1Delegate
- (void)viewControllerWillClose:(ViewController *)viewController {
    NSLog(@"LOG_viewControllerWillClose");
    NSRect windowFrame =self.window.contentView.frame;
    NSRect viewNewFrame = NSMakeRect(windowFrame.size.width, 0, windowFrame.size.width, windowFrame.size.height);
    [self moveAnimationWithView:_viewController.view location:viewNewFrame];
    [self moveAnimationWithView:self.windowBackView location:windowFrame];
}

Demo地址:

窗口动画切换demo