web-dev-qa-db-ja.com

iOS7より前のUINavigationController pushViewControllerアニメーションを復元する

そう。私のIOSコードをIOS7に移行し始めたところ、ちょっとした問題にぶつかりました。

UINavigationControllerがあり、これには子ViewControllersがあり、pushViewControllerを使用して次のビューを表示しています。画像のセットで視差アニメーションを作成するには、UINavigationControllerをカスタマイズしてUIImageViewsのセットをアニメーション化し、私の子ViewControllersにはすべてself.backgroundColor = [UIColor clearColor]、透明度。

IOS7以降、UINavControllerが子vcをアニメーション化する方法は、現在のView Controllerを部分的に移動し、新しいViewControllerを押すことによって更新されるため、視差アニメーションはくだらないように見えます。以前のVC少し移動して消えます。以前のUINavigationController pushViewControllerアニメーションを復元する方法はありますか?コード内でこれを見つけることができないようです。 。

WelcomeLoginViewController* welcomeLoginViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"WelcomeLogin"];
    [self.navigationController pushViewController:welcomeLoginViewController animated:YES];    

使用してみました:

    [UIView animateWithDuration:0.75
                     animations:^{
                         [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                         [self.navigationController pushViewController:welcomeLoginViewController animated:NO];
                         [UIView setAnimationTransition:<specific_animation_form> forView:self.navigationController.view cache:NO];
                     }];

誰にも手がかりがありますか?

38

フィードバックをありがとう。 UINavigationControllerの動作を完全に再現するソリューションを見つけました。ほぼ終了したとき、Nick Lockwoodのソリューションに出会いました。

https://github.com/nicklockwood/OSNavigationController

OSNavigationControllerは、UINavigationControllerのオープンソースの再実装です。現在、UINavigationControllerの機能のサブセットのみが機能していますが、長期的な目的は機能の100%を複製することです。

OSNavigationControllerは、実際にそのまま使用するためのものではありません。アイデアは、それをフォークしてから、アプリの特別な要件に合わせて外観と動作を簡単にカスタマイズできるということです。 OSNavigationControllerのカスタマイズは、コードが開いており、プライベートメソッド、文書化されていない動作、またはバージョン間の実装の変更を心配する必要がないため、UINavigationControllerをカスタマイズするよりもはるかに簡単です。

UINavigationControllerを彼のコードでオーバーライドすることで、UINavigationcontrollersで背景画像を操作することができました

ありがとう!

2

UINavigationControllerのカテゴリを作成することで、新しい遷移タイプを回避できました。私の場合、静的な背景の上をスライドする透明なviewControllerがあるため、古い移行スタイルに戻す必要がありました。

  • UINavigationController + Retro.h

    @interface UINavigationController (Retro)
    
    - (void)pushViewControllerRetro:(UIViewController *)viewController;
    - (void)popViewControllerRetro;
    
    @end
    
  • UINavigationController + Retro.m

    #import "UINavigationController+Retro.h"
    
    @implementation UINavigationController (Retro)
    
    - (void)pushViewControllerRetro:(UIViewController *)viewController {
        CATransition *transition = [CATransition animation];
        transition.duration = 0.25;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        transition.type = kCATransitionPush;
        transition.subtype = kCATransitionFromRight;
        [self.view.layer addAnimation:transition forKey:nil];
    
        [self pushViewController:viewController animated:NO];
    }
    
    - (void)popViewControllerRetro {
        CATransition *transition = [CATransition animation];
        transition.duration = 0.25;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        transition.type = kCATransitionPush;
        transition.subtype = kCATransitionFromLeft;
        [self.view.layer addAnimation:transition forKey:nil];
    
        [self popViewControllerAnimated:NO];
    }
    
    @end
    
46
Arne

クリアな背景色とくだらないアニメーションでも同じ問題が発生するため、新しいiOS7 APIを使用してViewControllerのカスタムトランジションを作成します。必要なのは、Navigation Controllerのデリゲートを設定するだけです。

// NavigationController does not retain delegate, so you should hold it.
self.navigationController.delegate = self.navigationTransitioningDelegate;

このファイルをプロジェクトに追加するだけです: MGNavigationTransitioningDelegate

22
ArtFeel

UIViewController AがpushViewControllerを実行してUIViewController Bをプッシュすると、プッシュアニメーションが約25%で停止し、停止してから、残りの方法でBをスライドさせるという問題がありました。

これはDID iOS 6では発生しませんが、iOS 7をXCode 5のベースSDKとして使用し始めるとすぐに発生し始めました。

修正点は、View Controller BのルートビューにbackgroundColorが設定されていないことです(ルートビューは、viewController.viewの値であり、通常はloadViewで設定します)。そのルートビューの初期化子でbackgroundColorを設定すると、問題が修正されました。

これを次のように修正できました。

// CASE 1: The root view for a UIViewController subclass that had a halting animation

- (id)initWithFrame:(CGRect)frame

{

     if ((self = [super initWithFrame:frame])) {

          // Do some initialization ...

          // self.backgroundColor was NOT being set

          // and animation in pushViewController was slow and stopped at 25% and paused

     }

     return self;

}

// CASE 2: HERE IS THE FIX

- (id)initWithFrame:(CGRect)frame

{

     if ((self = [super initWithFrame:frame])) {

          // Do some initialization ...

          // Set self.backgroundColor for the fix!

          // and animation in pushViewController is no longer slow and and no longer stopped at 25% and paused

          self.backgroundColor = [UIColor whiteColor]; // or some other non-clear color

     }

     return self;

}
18
Joel

まず、ストーリーボードを使用していません。 UINavigationController + Retroを使用してみました。何らかの理由で、UINavigationControllerがスタックの一番上にあるUIViewControllerを解放するのに苦労しています。 iOS 7のカスタムトランジションを使用して、私にとって有効なソリューションを次に示します。

  1. デリゲートをselfに設定します。

    navigationController.delegate = self;
    
  2. このUINavigationControllerDelegateを宣言します。

    - (id<UIViewControllerAnimatedTransitioning>)navigationController (UINavigationController *)navigationController 
    animationControllerForOperation:(UINavigationControllerOperation)operation
    fromViewController:(UIViewController *)fromVC 
    toViewController:(UIViewController *)toVC 
    {
        TransitionAnimator *animator = [TransitionAnimator new]; 
        animator.presenting = YES;
        return animator;
    }
    

    アニメーションがYESに設定されている場合にのみ呼び出されることに注意してください。例えば

    [navigationController pushViewController:currentViewController animated:YES];
    
  3. NSObjectを拡張するアニメータークラスを作成します。私は IViewController-Transitions-Example 内のTeehanLaxのTLTransitionAnimatorから変更された私のTransitionAnimatorを呼び出しました。

    TransitionAnimator.h

    #import <Foundation/Foundation.h>
    @interface TransitionAnimator : NSObject <UIViewControllerAnimatedTransitioning>
    @property (nonatomic, assign, getter = isPresenting) BOOL presenting;
    @end
    

    TransitionAnimator.m

    #import "TransitionAnimator.h"
    @implementation TransitionAnimator
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
        return 0.5f;
    }
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
        UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];    
        if (self.presenting) {
            //ANIMATE VC ENTERING FROM THE RIGHT SIDE OF THE SCREEN
            [transitionContext.containerView addSubview:fromVC.view];
            [transitionContext.containerView addSubview:toVC.view];     
            toVC.view.frame = CGRectMake(0, 0, 2*APP_W0, APP_H0); //SET ORIGINAL POSITION toVC OFF TO THE RIGHT                
            [UIView animateWithDuration:[self transitionDuration:transitionContext] 
                animations:^{
                    fromVC.view.frame = CGRectMake(0, (-1)*APP_W0, APP_W0, APP_H0); //MOVE fromVC OFF TO THE LEFT
                    toVC.view.frame = CGRectMake(0, 0, APP_W0, APP_H0); //ANIMATE toVC IN TO OCCUPY THE SCREEN
                } completion:^(BOOL finished) {
                    [transitionContext completeTransition:YES];
                }];
        }else{
            //ANIMATE VC EXITING TO THE RIGHT SIDE OF THE SCREEN
        }
    }
    @end
    

    提示フラグを使用して、アニメーション化する方向、または好みの条件を設定します。 link to Appleリファレンス。

7
voratima

単に追加する:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

この:

[[self window] setBackgroundColor:[UIColor whiteColor]];

最終結果:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {    
    [[self window] setBackgroundColor:[UIColor whiteColor]];

    // Override point for customization after application launch.
    return YES;
}
2
Riko87

どうやらiOS7には、独自のカスタムUIViewControllerトランジションを定義する新しい方法があります。 UIViewControllerTransitioningDelegateのドキュメントをご覧ください。また、それについての記事へのリンクは次のとおりです。 http://www.doubleencore.com/2013/09/ios-7-custom-transitions/

1
John Jacecko

役立つ別の素晴らしいリソースを見つけました:

http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions

IOS7 TLTransitionAnimatorを使用してカスタムアニメーションを作成する

0

@Arneの答えに投票しました。この問題に対する最もエレガントな解決策だからです。 @Arneのソリューションに関するコメントから@Billの問題に答えるために、いくつかのコードを追加したいと思います。コメントの引用は次のとおりです。

おかげで、これは私のために動作します。ただし、ユーザーが[戻る]ボタンをタップすると、バストされたアニメーションに戻ります([戻る]ボタンはpopViewControllerRetroを呼び出さないため)。 –ビル10月3日12時36分

戻るボタンが押されたときにpopViewControllerRetroを呼び出すために、これを実現するために実行できる小さなハックがあります。プッシュされたView Controllerに移動し、UIViewController + Retro.hをインポートして、viewWillDisappearメソッドに次のコードを追加します。

- (void)viewWillDisappear:(BOOL)animated {
    if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
        [self.navigationController popViewControllerRetro];
    }

    [super viewWillDisappear:animated];
}

このifステートメントは、[戻る]ボタンが押されたことを検出し、カテゴリクラスからpopViewControllerRetroを呼び出します。

宜しくお願いします。

0
uerceg