2

新しいプッシュ セグエは私のアプリではうまく動作しないため、iOS6 からの古いセグエ プッシュをシミュレートするカスタム セグエを作成しようとしました。

-(void)perform {

    UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
    UIViewController *destinationController = (UIViewController*)[self destinationViewController];

    CATransition* transition = [CATransition animation];
    transition.duration = 1.5;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
    transition.subtype = kCATransitionFromRight; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom



    [sourceViewController.navigationController.view.layer addAnimation:transition
                                                                forKey:kCATransition];

    [sourceViewController.navigationController pushViewController:destinationController animated:NO];

}

すべてがナビゲーション コントローラーに組み込まれています。「上部バーの下」と「下部バーの下」のエッジを延長するようにマークしました。また、両方のビュー コントローラー (ソースと宛先) でビューのカスタム背景色を設定しています。これら 2 つのビュー コントローラー間の移行中に、ナビゲーション バーが白と両方のビュー コントローラーのカスタム背景色の間でちらつき始めます。理由はありますか?

4

1 に答える 1

4

コードの問題は次のとおりです。

pushViewControllerメソッドをトリガーするsourceViewControllerと、 がナビゲーション スタックからすぐに削除され、 が表示されdestinationViewControllerます。これにより、アニメーションに問題が発生します (この問題は iOS 6 でも存在し、別の問題である「黒いフェード」を引き起こします)。それでも使用したい場合pushViewController(ナビゲーション ロジックを再構築する必要がないため簡単です)、Apple の提案に従って実行する必要があります。

アニメーションの実行方法に関係なく、アニメーションの最後に、目的のビュー コントローラー (およびそのビュー) を適切な場所にインストールして、イベントを処理できるようにする必要があります。たとえば、カスタム モーダル トランジションを実装する場合、スナップショット イメージを使用してアニメーションを実行し、最後に presentModalViewController:animated: メソッドを (アニメーションを無効にして) 呼び出して、ソースと宛先の間の適切なモーダル関係を設定します。ビューコントローラー。

スナップショットを使用する必要があります。

ここで、実行メソッドが更新されました:

- (void)perform
{
    UIViewController *source = (UIViewController *) self.sourceViewController;
    UIViewController *destination = (UIViewController *) self.destinationViewController;

    // Swap the snapshot out for the source view controller
    UIWindow *window = source.view.window;
    UIImageView *screenShot = [[UIImageView alloc] initWithImage:[self screenshot]];

    BOOL animsEnabled = [UIView areAnimationsEnabled];
    [UIView setAnimationsEnabled:NO];

    [window addSubview:screenShot];

    [UIView setAnimationsEnabled:animsEnabled];

    CATransition* transition = [CATransition animation];
    transition.duration = 1.5;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
    transition.subtype = kCATransitionFromRight; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
    [source.navigationController pushViewController:destination animated:NO];
    [destination.navigationController.view.layer addAnimation:transition forKey:kCATransition];


    [UIView animateWithDuration:1.5f animations:^{
        screenShot.frame = CGRectOffset(screenShot.frame, -screenShot.frame.size.width, 0);
    } completion:^(BOOL finished) {
        [screenShot removeFromSuperview];
    }];
}

正しいスクリーンショットを作成するにrenderInContextは、半透明のバーのぼかしが正しく処理されていないため、単にメソッドを使用するだけでは十分ではありません。別の方法を見つけました(この質問からコピーして貼り付けました)

- (UIImage *)screenshot
{
    CGSize imageSize = CGSizeZero;

    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if (UIInterfaceOrientationIsPortrait(orientation)) {
        imageSize = [UIScreen mainScreen].bounds.size;
    } else {
        imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
    }

    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
        CGContextSaveGState(context);
        CGContextTranslateCTM(context, window.center.x, window.center.y);
        CGContextConcatCTM(context, window.transform);
        CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
        if (orientation == UIInterfaceOrientationLandscapeLeft) {
            CGContextRotateCTM(context, M_PI_2);
            CGContextTranslateCTM(context, 0, -imageSize.width);
        } else if (orientation == UIInterfaceOrientationLandscapeRight) {
            CGContextRotateCTM(context, -M_PI_2);
            CGContextTranslateCTM(context, -imageSize.height, 0);
        } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
            CGContextRotateCTM(context, M_PI);
            CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
        }
        if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
            [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
        } else {
            [window.layer renderInContext:context];
        }
        CGContextRestoreGState(context);
    }

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

どのように動作するかを示すサンプル プロジェクトを添付します:サンプル プロジェクトへのリンク

于 2013-12-04T10:40:17.570 に答える