在调用completeTransition之后,导航栏被调整:在自定义转换中

我的目标是在启动应用程序时从类似于跳板图标的视图中为用户提供缩放模式转换。

所呈现的视图控制器正确放大,但导航栏在状态栏下的位置错误。 调用[transitionContext completeTransition:finished]后,该位置得到纠正。 如何从转换开始就使它正确无误?

这是一个屏幕logging的错误:http: //youtu.be/7LKU4lzb-uw (故障是在第六秒的logging)

UIViewControllerAnimatedTransitioning代码:

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *container = [transitionContext containerView]; CGPoint viewCenter = self.view.center; CGSize viewSize = self.view.frame.size; CGSize controllerSize = toViewController.view.frame.size; CGFloat controllerFromX = viewCenter.x - (controllerSize.width / 2); CGFloat controllerFromY = viewCenter.y - (controllerSize.height / 2); CGAffineTransform transform = CGAffineTransformMakeTranslation(controllerFromX, controllerFromY); transform = CGAffineTransformScale(transform, viewSize.width / controllerSize.width, viewSize.height / controllerSize.height); if (self.reverse) { [container insertSubview:toViewController.view belowSubview:fromViewController.view]; } else { toViewController.view.transform = transform; [container addSubview:toViewController.view]; } [UIView animateKeyframesWithDuration:ZoomTransitioningDuration delay:0 options:0 animations:^{ if (self.reverse) { fromViewController.view.alpha = 0.0f; fromViewController.view.transform = transform; } else { toViewController.view.transform = CGAffineTransformIdentity; } } completion:^(BOOL finished) { [transitionContext completeTransition:finished]; }]; } 

问题是, 将目标视图控制器的视图插入容器之前 ,您正在设置转换。

切换顺序应该修复它:

 if (self.reverse) { [container insertSubview:toViewController.view belowSubview:fromViewController.view]; } else { [container addSubview:toViewController.view]; toViewController.view.transform = transform; } 

在这里见第4点。 由于在将导航控制器的视图作为子视图插入之前已经应用了一个转换,所以布局引擎不认为导航栏位于窗口的顶部边缘,因此不需要进行调整以避免状态酒吧。

我find了一个解决scheme,虽然很hacky。 我必须在animation开始之前手动调整导航栏框架:

 if (self.reverse) { [container insertSubview:toViewController.view belowSubview:fromViewController.view]; } else { toViewController.view.transform = transform; [container addSubview:toViewController.view]; // fix navigation bar position to prevent jump when completeTransition: is called if ([toViewController isKindOfClass:[UINavigationController class]]) { UINavigationController* navigationController = (UINavigationController*) toViewController; UINavigationBar* bar = navigationController.navigationBar; CGRect frame = bar.frame; bar.frame = CGRectMake(frame.origin.x, frame.origin.y + 20.0f, frame.size.width, frame.size.height); } } 

首先将toViewControllerView添加到ContainerView,然后如下所示设置toViewControllerView变换。

[container addSubview:toViewController.view];

toViewController.view.transform = transform;

这将解决问题。

这仍然是一个黑客,基于OndřejMirtes的一个,但如果你有一个通话状态栏,并且你在iOS8上

 if([toViewController isKindOfClass:[UINavigationController class]]) { UINavigationController *navCtrl = (UINavigationController *)toViewController; UINavigationBar *navBar = navCtrl.navigationBar; if(navBar.frame.origin.y == 0 && navBar.frame.size.height == 44) { navBar.frame = CGRectMake(0, 0, navBar.frame.size.width, fmin(44 + [UIApplication sharedApplication].statusBarFrame.size.height, 64)); } } 

仍然丑陋:/