【问题标题】:CATransition also animating the navigationBarCATransition 还为导航栏设置动画
【发布时间】:2012-08-20 06:22:27
【问题描述】:

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

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];

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

【问题讨论】:

  • 如果你能告诉我们上面的代码 sn-p 是在哪里执行的,那将是有益的? (在标签栏的委托方法中?在另一个父视图控制器中?,...)您是否在 viedDidLoad 事件中调用上述代码?
  • @NenadMihajlovic 当我在导航栏中的默认后退按钮被触摸时调用它

标签: objective-c uiview uinavigationcontroller catransition


【解决方案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 可以满足您作为自定义视图控制器行为的指定方式的需求。

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多