CATransition还可以为navigationBar设置动画

时间:2012-08-20 06:22:27

标签: objective-c uiview uinavigationcontroller catransition

我想制作一个自定义动画来弹出我的导航控制器。我只想动画视图,而不是navigationBar。使用此代码,我可以为视图和navigationBar设置动画。我怎样才能为视图设置动画?

CATransition* transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;

[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];

当按下导航控制器栏中添加的自定义后退按钮时,将触发此代码。

1 个答案:

答案 0 :(得分:1)

这是一个代码,可以为后退按钮和调用popRootViewController:方法时执行自定义动画。

这是一个扩展UINavigationViewController的类,它本身与Apple的文档相矛盾,它也使用KVO分配私有变量,一旦工程师更改UINavigationController类,它可能会停止工作,因此使用它需要您自担风险。

#import "MyNavigationController.h"

@interface MyNavigationController () <UINavigationBarDelegate> {
    // Flag that we will use to avoid collisions between navgiation bar
    // when we call popViewControllerAnimated: method directly
    BOOL _isPopping;
}
- (UIViewController *)myPopViewControllerAniamted:(BOOL)animated;
@end

@implementation MyNavigationController

- (id)init
{
    self = [super init];
    if (!self) return nil;
    // We can't intercept delegation of the original navigation bar,
    // we have to replace it with our own, by assigning new instance to
    // the private _navigationBar vairable
    UINavigationBar *navigationBar = [[UINavigationBar alloc] init];
    navigationBar.delegate = self;
    [self setValue:navigationBar forKey:@"_navigationBar"];

    return self;
}

// This is the delegate method called when you're about to pop navigation item
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
// If we're in the process of popping items we don't want to reenter
    if (!_isPopping) {
        [self myPopViewControllerAniamted:YES];
    }
    return YES;
}

// Similarly we have to override popToRootViewControllerAnimated:
// The only difference would be that we use not previous view as a
// target for the transfition, but the very first view
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
    return [self myPopViewControllerAniamted:animated];
}

// Our custom popping method
- (UIViewController *)myPopViewControllerAniamted:(BOOL)animated
{
    _isPopping = YES;
    // If we got here, we have at least two view controllers in the stack
    UIViewController *currentViewController = self.topViewController;
    if (animated && self.viewControllers.count > 1) {
        UIView *currentView = currentViewController.view;
        UIViewController *previousViewController = [self.viewControllers objectAtIndex:self.viewControllers.count - 2];
        UIView *previousView = previousViewController.view;
        previousView.alpha = 0.0;
        [currentView.superview insertSubview:previousView belowSubview:currentView];
        // I use UIView just for the sake of the simplicity of this example
        // In case of core animation you will have to deal with delegates
        // to trigger view controller popping when animation finishes
        [UIView animateWithDuration:0.33 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            currentView.alpha = 0.0;
            previousView.alpha = 1.0;
        } completion:^(BOOL finished) {
            [super popViewControllerAnimated:NO];
            _isPopping = NO;
        }];
    } else {
        [super popViewControllerAnimated:NO];
        _isPopping = NO;
    }
    return currentViewController;
}

@end

再一次,它完全是为了尽可能地运用,我强烈建议阅读UIViewController guide,可能Container View Controller可以满足您的需求,作为自定义视图控制器行为的指定方式。

希望它有所帮助!