18

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

呈现的视图控制器正确放大,但导航栏在状态栏下的位置错误。此位置在调用 [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];
        }];
}
4

4 回答 4

27

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

切换顺序应该可以解决它:

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

请参阅此处的第 4 点。由于您在将导航控制器的视图作为子视图插入之前应用了转换,因此布局引擎不会认为导航栏位于窗口的顶部边缘,因此不需要调整以避免状态酒吧。

于 2013-10-23T00:56:37.953 回答
6

我找到了一个解决方案,虽然很老套。我必须在动画开始之前手动调整导航栏框架:

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);
    }
}
于 2013-09-25T19:14:29.853 回答
1

Add the toViewControllerView first to the ContainerView, then set the toViewControllerView transform as given below.

[container addSubview:toViewController.view];

toViewController.view.transform = transform;

This will solve the problem.

于 2014-11-04T09:27:42.690 回答
0

这仍然是一个 hack,基于 Ondřej Mirtes 的一个,但如果你有一个通话状态栏并且你在 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)); 
  }
}

虽然仍然很丑:/

于 2014-09-29T11:07:00.083 回答