web-dev-qa-db-ja.com

iOS7 UIModalTransitionStyleFlipHorizo​​ntalが移行後にバウンスする

IOS 7用にアプリを更新していますが、奇妙な問題を発見しました。 UIModalTransitionStyleFlipHorizontalを使用してUINavigationControllerにラップされたUIViewControllerを提示しています。

IOS 6では正常に動作しますが、iOS 7では、移行後にナビゲーションバーがバウンスします。これはステータスバーと関係がありますか?メインナビゲーションバーの半透明度をNOに設定しました。

Info.plistでは、View controller-based status bar appearがNOに設定されています。

そして、これが最小限のデモアプリでの問題を示すGIFです。

enter image description here

これが私のコードです:

feedNavigationController = [[UINavigationController alloc] init];
feedNavigationController.navigationBar.translucent = NO;

SettingsViewController *settingsVC = [[SettingsViewController alloc] init];

feedNavigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[feedNavigationController setViewControllers:[NSArray arrayWithObjects:settingsVC, nil]];

[self presentViewController:feedNavigationController animated:YES completion:nil];
73
Rene

これはUIKitのバグのようです。次の回避策で問題が解決したようです。

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.navigationController.navigationBar.layer removeAllAnimations];
}

(これを、移行するビューコントローラーに配置しますto)。

54
Ben Packard

この問題を解決して解決するには、iOS7カスタムトランジションを使用します。

これをあなたのUIViewControllerに追加してください:

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
    return (id<UIViewControllerAnimatedTransitioning>)self;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    return (id<UIViewControllerAnimatedTransitioning>)self;
}

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
    return 0.7f;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    UIView *containerView = [transitionContext containerView];


    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    [containerView addSubview:fromVC.view];

    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    [containerView addSubview:toVC.view];

    UIViewAnimationOptions animationOption = ([toVC.presentedViewController isEqual:fromVC])?UIViewAnimationOptionTransitionFlipFromLeft:UIViewAnimationOptionTransitionFlipFromRight;


    [UIView transitionFromView:fromVC.view
                        toView:toVC.view
                      duration:[self transitionDuration:transitionContext]
                       options:animationOption
                    completion:^(BOOL finished) {
                        [transitionContext completeTransition:YES];
                    }];
}

これを使用するには、iOS7を使用しているかどうかを確認し、transitionDelegateを設定するだけです。

YourVCWithTheCustomTransition* yourVC = [[YourVCWithTheCustomTransition alloc] init];

CGFloat deviceVersion = [UIDevice currentDevice].systemVersion.floatValue;
if(deviceVersion >= 7.0) [yourVC setTransitioningDelegate:yourVC];

[self presentModalViewController:yourVC animated:YES];
[yourVC release];

私の場合、カスタム遷移が定義されているカスタムUINavigationControllerがありました。毎回これを行う必要はありません。

16
EricD

これはUIKitのバグのようです。次の回避策で問題が解決したようです。

presentViewController(これを移行先のビューコントローラーに配置します):

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.navigationController.navigationBar.layer removeAllAnimations];
}

dismissViewControllerAnimated(これを却下するビューコントローラーに配置します):

- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

    [self.navigationController.navigationBar.layer removeAllAnimations];
}

autolayoutを使用しない場合。これをdismissのビューコントローラに追加する必要があります。

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    [self.view setNeedsLayout];
} 
9
dusty

私は同じ問題を抱えており、「解決する」ことができました(それは問題の実際の解決策ではありませんが、問題なく見えます:))。トリックは、フリップフロップを作成するためにpushViewControllerアニメーションでpopViewController/UIViewを使用してビューコントローラを表示することです。以下は、ビューコントローラーを表示するコードの例です。

UIViewController *viewController = [[UIViewController alloc] init];
[UIView transitionWithView:self.navigationController.view 
                  duration:0.5 
                   options:UIViewAnimationOptionTransitionFlipFromLeft 
                animations:^{
                   [self.navigationController pushViewController:viewController animated:NO];
                }
                completion:nil];

それを閉じるには:

[UIView transitionWithView:self.navigationController.view 
                  duration:0.5 
                   options:UIViewAnimationOptionTransitionFlipFromRight 
                animations:^{
                   [self.navigationController popViewControllerAnimated:NO];
                }
                completion:nil];

プッシュされたコントローラーでnavigationBarが不要な場合は、viewWillAppear[self.navigationController setNavigationBarHidden:YES animated:NO]を呼び出します。このアプローチがお役に立てば幸いです。

3
RemeR

提示するビューコントローラーと提示されるビューコントローラーの両方について、UITableViewController内にUINavigationControllerがあり、どちらも自動レイアウトを使用して構成されています。他の回答では、表示するビューコントローラーのtableViewを閉じると垂直方向に20 ptジャンプするという問題が解決されないことに気付きました。

このソリューションはこの問題に対処します。

提示されたビューコントローラー(Ben Packardによって提案されたもの)で:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.navigationController.navigationBar.layer removeAllAnimations];
}

プレゼンテーションビューコントローラで(部分的にほこりっぽく提案されているように):

- (void)viewWillLayoutSubviews{
    if (self.navigationController.presentedViewController) {
        [self.navigationController.navigationBar.layer removeAllAnimations];
        [self.tableView.layer removeAllAnimations];
    }
    [super viewWillLayoutSubviews];
}
1
Ortwin Gentz