过渡后iOS7 UIModalTransitionStyleFlipHorizo​​ntal弹跳


73

我正在为iOS 7更新我的应用程序,发现一个奇怪的问题。我正在用呈现一个包装在UINavigationController中的UIViewController UIModalTransitionStyleFlipHorizontal

在iOS 6中,它可以正常工作,但在iOS 7中,过渡后导航栏会反弹。这与状态栏有关吗?我已将主导航栏的透明度设置为NO

在Info.plist中,基于View控制器的状态栏外观设置为NO。

这是一个在最小的演示应用程序中显示问题的GIF:

在此处输入图片说明

这是我的代码:

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

很遗憾,找不到视频。
Tim Bodeit 2013年

2
我有同样的问题。
flypig 2013年

完全一样的问题,GM版本有一些Biig问题,collectionView reloadData也是一个问题!
jasonIM

1
不适合我!iOS 8仍然存在此问题。视图中的self.navigationController?.navigationBar.layer.removeAllAnimations()会为我修复。
nmdias

1
与我的项目一样,在iOS9上,我使用UIView transitionFromView:toView:duration:options:completion:在两个ViewController之间切换并遇到此错误。遵循答案可以解决导航栏高度问题,但不能解决其色调问题,有人遇到了这个问题吗?
eagle.dan.1349

Answers:


54

这似乎是一个UIKit错误。以下变通办法似乎可以为我解决问题。

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

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

(将其放置在您要转换的视图控制器)。


这对我有用。确保在导航控制器的根视图控制器中执行此操作,而不是在导航控制器本身中执行。
alexcash13年

有趣-解雇后究竟会发生什么?
Ben Packard 2013年

解雇也发生同样的事情。因此,这只能部分解决问题。将其添加到开始过渡的视图控制器(from视图控制器)并不能解决退出和过渡后的问题。
菲利普(Philip)

我知道-我是从没有导航栏的控制器翻转过来的,所以从未遇到过。从技术上讲,它解决了所述问题;)
Ben Packard 2013年

5
一次调用该动画对我有效,但随后的任何调用均不起作用。为什么会这样,因为每次视图出现时都会调用它?疯了
马特·米勒

16

为了解决此问题,我使用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,其中定义了自定义过渡:我不必每次都这样做。


与“ else yourVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizo​​ntal;”的添加效果很好。在deviceVersion的测试中,因此它可以继续在iOS6中工作。
LavaSlider 2013年

这应该是公认的答案。完美运作。我唯一的建议是将这段代码放在一个单独的类中,然后可以在任何View Controller中使用。
mluisbrown 2014年

3
不检查系统版本,而是检查该方法是否可用:if ([yourVC respondsToSelector:@selector(setTransitioningDelegate:)] { [yourVC setTransitioningDelegate:yourVC]; }
rckoenes 2014年

很好,但我要做的只是将委托设置为“ viewwillappear”,因为我的某些视图是通过情节提要编辑器定义的。
伊姆兰(Imran)2014年

有趣的是,从此过渡返回可能导致iOS 8下出现永久性白屏。当然,在iOS 8下您不需要执行任何此操作,因为修正了此必要的错误。
user564904 2014年

9

这似乎是一个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];
} 

抱歉,我上次粘贴了错误的代码。这段代码对我有用。
雨果

在我看来,这绝对有效。分镜脚本
Roger

我可以确认这对我也有效。iOS 7.1.1
AlBeebe 2014年

3

我遇到了同样的问题,可以“解决它”(这不是解决问题的真正方法,但看起来还不错:))。诀窍是本使用视图控制器pushViewController/popViewControllerUIView动画制作倒装。这是呈现视图控制器的示例代码:

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在推送的控制器上调用[self.navigationController setNavigationBarHidden:YES animated:NO]in viewWillAppear。希望这种方法对您有所帮助。


1
这实际上解决了过渡双方的问题,而上述答案并没有解决。如果模态控制器上有导航栏,则可能需要将左栏按钮项设置为nil,以获得与在iOS6上完全相同的效果(无后退按钮),仅此而已。

1
顺便说一句,由于某种原因,此方法导致导航栏中的视觉故障(尽管不如不使用它严重)。主要是,标题和后退按钮文本直到转换后才显示,并且在转换过程中为空白。

这应该是公认的答案,这是双向转换的理想解决方法。只需在视图中根据需要检查隐藏底部栏和隐藏/取消隐藏导航栏,就会显示推动和推动控制器的方法。
raladdin

1

对于呈现和呈现的视图控制器,我都有一个UITableViewController内部UINavigationController,均使用自动布局进行配置。我注意到其他答案并不能解决当前呈现的视图控制器的tableView垂直跳20磅的问题。

该解决方案解决了这个问题。

在呈现的视图控制器(由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];
}

-2

我也一样。实际起作用的是将样式更改为CoverVertical,看起来更加流畅。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.