我正在为 iOS 7 更新我的应用程序,但我发现了一个奇怪的问题。我正在展示一个用 UIModalTransitionStyleFlipHorizontal
包装在 UINavigationController 中的 UIViewController。
在 iOS 6 中它可以正常工作,但在 iOS 7 中导航栏在转换后会弹跳。这和状态栏有关系吗?我已将主导航栏的半透明设置为 NO
。
在 Info.plist 中,基于视图控制器的状态栏外观设置为 NO。
这是一个 GIF 在一个最小的演示应用程序中显示问题:
https://i.stack.imgur.com/EznOv.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];
这似乎是一个 UIKit 错误。以下解决方法似乎为我解决了这个问题。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController.navigationBar.layer removeAllAnimations];
}
(将其放置在您要转换到的视图控制器中)。
为了解决这个问题,我使用了 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 ,其中定义了自定义转换:我不必每次都这样做。
if ([yourVC respondsToSelector:@selector(setTransitioningDelegate:)] { [yourVC setTransitioningDelegate:yourVC]; }
这似乎是一个 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];
}
我有同样的问题并且可以“解决它”(这不是问题的真正解决方案,但看起来不错:))。诀窍是使用带有 UIView
动画的 pushViewController
/popViewController
呈现视图控制器以进行翻转。下面是展示视图控制器的示例代码:
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]
。我希望这种方法对您有所帮助。
对于呈现和呈现的视图控制器,我在 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];
}
我也一样。实际工作是将样式更改为 CoverVertical,看起来更平滑。