我的目标是为用户提供缩放模式转换,类似于跳板图标在启动应用时放大的视图。
呈现的视图控制器正确放大,但导航栏在状态栏下位置错误。调用[transitionContext completeTransition:finished];后,该位置得到纠正。如何从过渡开始就使其正确?
这是错误的屏幕录制:http://youtu.be/7LKU4lzb-uw(小故障在录音的第6秒)
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];
}];
}
答案 0 :(得分:26)
问题是您正在设置转换 之前将目标视图控制器的视图插入容器。
切换订单应修复它:
if (self.reverse) {
[container insertSubview:toViewController.view belowSubview:fromViewController.view];
} else {
[container addSubview:toViewController.view];
toViewController.view.transform = transform;
}
见第4点here。由于您在将导航控制器的视图作为子视图插入之前应用了变换,因此布局引擎不认为导航栏位于窗口的顶部边缘,因此无需调整以避免状态杆
答案 1 :(得分:6)
我找到了一个解决方案,虽然非常hacky。我必须在动画开始前手动调整导航栏框架:
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);
}
}
答案 2 :(得分:1)
首先将toViewControllerView添加到ContainerView,然后设置toViewControllerView变换,如下所示。
[container addSubview:toViewController.view];
toViewController.view.transform = transform;
这将解决问题。
答案 3 :(得分:0)
这仍然是一个黑客,基于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));
}
}
但仍然很难看:/