18

My goal is to provide zooming modal transition from for the user from a view similar as springboard icons zoom in when launching apps.

The presented view controller zooms in correctly, but the navigation bar has wrong position under the status bar. This position gets corrected after calling [transitionContext completeTransition:finished];. How can I make it correct from the beginning of the transition?

This is a screen recording of the bug: http://youtu.be/7LKU4lzb-uw (the glitch is in the 6th second of the recording)

The UIViewControllerAnimatedTransitioning code:

- (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 に答える