0

ナビゲーション コントローラーをポップするカスタム アニメーションを作成したいと考えています。ナビゲーションバーではなく、ビューのみをアニメーション化したい。このコードを使用して、ビューとナビゲーション バーの両方をアニメーション化します。ビューのみをアニメーション化するにはどうすればよいですか??

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

このコードは、ナビゲーション コントローラー バー内に追加されたカスタムの戻るボタンが押されたときに発生します。

4

1 に答える 1

1

これは、戻るボタンとメソッドを呼び出すときの両方でカスタム アニメーションを実行するコードですpopRootViewController:

これは、それ自体が Apple のドキュメントと矛盾する拡張クラスでUINavigationViewControllerあり、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 ガイドを読むことを強くお勧めします。おそらく、Container View Controllerは、View Controllerの動作をカスタマイズする指定された方法としてニーズを満たすことができます。

それが役に立てば幸い!

于 2012-08-20T07:50:09.823 に答える