iOS7 UIModalTransitionStyleFlipHorizo​​ntal 过渡后反弹

Posted

技术标签:

【中文标题】iOS7 UIModalTransitionStyleFlipHorizo​​ntal 过渡后反弹【英文标题】:iOS7 UIModalTransitionStyleFlipHorizontal bounces after transition 【发布时间】:2013-09-17 20:35:55 【问题描述】:

我正在为 ios 7 更新我的应用程序,但我发现了一个奇怪的问题。我正在展示一个 UIViewController 包装在带有 UIModalTransitionStyleFlipHorizontal 的 UINavigationController 中。

在 iOS 6 中它可以正常工作,但在 iOS 7 中导航栏在转换后会弹跳。这和状态栏有关系吗?我已将主导航栏的半透明设置为NO

在 Info.plist 中,基于视图控制器的状态栏外观设置为 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];

【问题讨论】:

很遗憾找不到视频。 我也有同样的问题。 完全相同的问题,GM 版本有一些 Biig 问题,collectionView reloadData 也是一个! 不适合我! iOS 8 仍然存在这个问题。视图中的 self.navigationController?.navigationBar.layer.removeAllAnimations() 将为我修复它。 在我的项目中也是如此,在 iOS9 上,我使用 UIView transitionFromView:toView:duration:options:completion: 在两个视图控制器之间切换并面临这个错误。以下答案解决了导航栏高度的问题,但不是它的色调,有人遇到过这个问题吗? 【参考方案1】:

这似乎是一个 UIKit 错误。以下解决方法似乎可以解决我的问题。

- (void)viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];

    [self.navigationController.navigationBar.layer removeAllAnimations];

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

【讨论】:

这对我有用。确保在导航控制器的根视图控制器中执行此操作,而不是导航控制器本身。 有趣 - 解雇时究竟会发生什么? 解雇时也会发生同样的事情。所以这只能部分解决问题。将此添加到开始转换的视图控制器(来自视图控制器)并不能解决关闭和转换回来时的问题。 我明白了 - 我从没有导航栏的控制器翻转,所以从来没有遇到过这种情况。从技术上讲,它解决了上述问题;) 这在第一次调用动画时对我有用,但在任何后续调用中都不起作用。为什么会这样,因为每次视图出现时都会调用它???令人抓狂。【参考方案2】:

对我来说也一样。实际可行的是将样式更改为 CoverVertical,看起来更流畅。

【讨论】:

【参考方案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,只需在viewWillAppear 中调用[self.navigationController setNavigationBarHidden:YES animated:NO]。我希望这种方法对您有所帮助。

【讨论】:

这实际上解决了过渡双方的问题,这不是上面的答案所做的。如果您在模态控制器上有一个导航栏,您可能需要将左栏按钮项设置为 nil 以获得您在 iOS6 上的确切效果(无后退按钮)但仅此而已。 顺便说一下,由于某种原因,此方法会导致导航栏出现视觉故障(尽管不如不使用它严重)。主要是标题和后退按钮文本直到过渡后才会显示,并且在过渡期间是空白的。 这应该是公认的答案,它是双向转换的完美解决方法。只需检查在推送时隐藏底部栏并根据需要在视图中隐藏/取消隐藏导航栏将出现推送和推送控制器的方法。【参考方案4】:

为了解决这个问题,我使用了 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 中继续工作。 这应该是公认的答案。完美运行。我唯一的建议是将这段代码放在一个单独的类中,然后您可以在任何视图控制器中使用它。 Don't check for the system version 但检查方法是否可用:if ([yourVC respondsToSelector:@selector(setTransitioningDelegate:)] [yourVC setTransitioningDelegate:yourVC]; 很好用,我唯一要做的就是将代理设置为“viewwillappear”,因为我的一些视图通过情节提要编辑器定义了转场。 有趣的是,在 iOS 8 下,从这个转换返回会导致永久的白屏。当然,在 iOS 8 下你不需要做任何这些,因为修复了这个必要的错误。 【参考方案5】:

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

【讨论】:

对不起,我上次贴错了代码。这段代码对我有用。 这对我来说绝对有效。故事板截图:cl.ly/image/060t10100b2W 我可以确认这对我也有效。 iOS 7.1.1【参考方案6】:

对于呈现和呈现的视图控制器,我在UINavigationController 中都有一个UITableViewController,两者都使用自动布局进行配置。我注意到其他答案并没有解决在关闭当前视图控制器的 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];

【讨论】:

以上是关于iOS7 UIModalTransitionStyleFlipHorizo​​ntal 过渡后反弹的主要内容,如果未能解决你的问题,请参考以下文章

iOS7 的视图大小和位置

iOS7 和 Apple Watch

ios7之后的一些更改

iOS7隐藏状态栏

在ios7中绘图时出现延迟

iOS7 后台获取