4

iPadで、モーダルプレゼンテーションスタイルUIModalPresentationPageSheetを使用してモーダルビューコントローラーを表示します。このビューコントローラーは、modalPresentationStyleUIModalPresentationFormSheetを使用して別のモーダルビューコントローラーを表示します。

したがって、フォームシートはページシートよりも小さいため、ユーザーには、背景ビューコントローラ、ページシート、およびフォームシートがすべて重なり合って表示されます。ページシートの表示により、背景が暗くなり、操作できなくなります。ただし、フォームシートはiOS 5のページシートを暗くしないため、ユーザーは下のページシートを操作できます。ただし、ページシートも暗くして、ユーザーがページシートを再度操作する前に、モーダルフォームシートを閉じる必要があるようにします。

iOS 4では、これがデフォルトの動作ですが、iOS5ではこれを実現する方法が見つかりませんでした。何か提案はありますか?

4

2 に答える 2

2

これは iOS5 のバグだと思います。他のモーダルからモーダル ビュー コントローラを提示する実験をいくつか行ったところ、2 番目のモーダルが下の画面を暗くすることはないようです。相互に無限のモーダルを起動できるようにするテスト プロジェクトをセットアップしましたが、他のすべてのモーダルが期待どおりに暗くなったり、タッチをブロックしたりしないようです。

UIWindow サブビューの簡単な NSLog は、ドロップ シャドウが適切に追加されている一方で、dimmingView が適切に追加されていないことを示しています。私は自分の調光ビューを表示する方法に取り組んでいます。方法が見つかったら、この回答を更新します。

Window Subviews: (
    "<UILayoutContainerView: 0xf63e3c0; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf645640>>",
    "<UIDimmingView: 0xf683990; frame = (0 0; 768 1024); opaque = NO; layer = <CALayer: 0xf6836d0>>",
    "<UIDropShadowView: 0xf683130; frame = (64 64; 640 896); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf6831c0>>",
    "<UIDropShadowView: 0x292110; frame = (74 242; 620 540); transform = [0, 1, -1, 0, 0, 0]; autoresize = LM+RM+TM+BM; layer = <CALayer: 0x292150>>"
)

解決策 2: アニメ調の最終的な解決策です。また、私は最初の解決策について考えなければなりませんでした。これは Apple を怒らせ、技術的に可能であり、UIDimmingView は文書化されておらず、私たちは「それに触れる」ため、拒否を引き起こします。ViewController に必要なアルファの背景色を持つ UIView を追加します。次に、モーダルを提示するときにそれをアニメーション化し、2 番目のモーダルのデリゲートが呼び出されたときにアニメーションを逆にします。私にはかなり良さそうです。たぶん、タイミングとアルファの微調整がちょうどいいものになるかもしれませんが、うまく機能し、見栄えがします。

- (void)viewDidLoad 
{
    dim = [[UIView alloc] init];
    [dim setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.35]];
    [dim setAlpha:0.0];
    [dim setUserInteractionEnabled:NO];
    [self.view addSubview:dim];
}

- (void)presentModal
{
    [self.view bringSubviewToFront:dim];
    [dim setFrame:self.view.frame];
    [UIView animateWithDuration:0.25 animations:^{
        [dim setAlpha:1.0];
    }];
}

- (void)modalDelegateFinished
{
    [UIView animateWithDuration:0.25 animations:^{
        [dim setAlpha:0.0];
    }];
}

解決策 1:

これでうまくいきましたが、私が望むほどアニメーション化されていません。しかし、それはすでにそこにあるものを再利用するので、おそらくそれにはプラスがあります.

- (void)viewDidAppear:(BOOL)animated
{
    // Add a gesture to dismiss the view if tapped outside.
    UIGesture *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedOutsideView:)];
    [gesture setNumberOfTapsRequired:1];
    [gesture setCancelsTouchesInView:NO];
    [self.view.window addGestureRecognizer:gesture];

    // Move the dimmingview to just below the dropshadow.
    UIView *dim = [self.view.window.subviews objectAtIndex:1];
    [self.view.window insertSubview:dim atIndex:2];
}

- (void)tappedOutsideView:(UITapGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateEnded) {
        CGPoint location = [sender locationInView:nil];

        if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) {
            // remove the gesture on the window
            [self.view.window removeGestureRecognizer:sender];

            // Move the dimmingview back where it belongs
            UIView *dim = [self.view.window.subviews objectAtIndex:2];
            [self.view.window insertSubview:dim atIndex:1];
        }
    }
}

また、フェイルセーフとして、viewDidDisappear の同じものにおそらく良い考えです。私の完了ボタンは tappedOutside ビューを呼び出すので、ジェスチャーと dimmingView が常に正しく配置されていることがわかります。しかし、そのようにしなかった場合は、viewDidDisappear に入れることができます。

- (void)viewDidDisappear:(BOOL)animated
{
    // remove the gesture on the window
    for (UIGestureRecognizer *gesture in self.view.window.gestureRecognizers) {
        [self.view.window removeGestureRecognizer:gesture];
    }

    // Move the dimmingview back where it belongs
    UIView *dim = [self.view.window.subviews objectAtIndex:2];
    [self.view.window insertSubview:dim atIndex:1];
}
于 2012-04-20T18:49:38.570 に答える
0

iOSのバグのようです。まだiOS7にあります。

これを回避するために私がしたことは次のとおりです(iOS7でテスト済み)。興味深いことに、モーダルの上にモーダルを表示しても、プレゼンターは暗くなりませんが、それらの上に表示される 3 番目のモーダルが表示されます。

これを知っていれば、実際のフォーム シート モーダルを表示する前にダミーを表示できます。これには最小限のコードが含まれ、技術的には一般的な iOS 設計パターンに沿っています。したがって、将来の爆発のリスクは最小限に抑えられるはずです。

最初にフォーム シートを提示します。

- (void)presentFormSheetModalOverThePageSheetModal
{
    //get the controller I'm trying to present and stick it in a nav controller - as usual
    UIViewController *myModalController = [UIViewController new];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myModalController];
    navController.modalPresentationStyle = UIModalPresentationFormSheet;

    //create an intermediate controller that will be presented first
    UIViewController *intermediateController = [UIViewController new];
    intermediateController.modalPresentationStyle = UIModalPresentationCurrentContext;
    intermediateController.view.backgroundColor = self.view.backgroundColor;

    //create a snapshot of self (presenting controller)
    UIView *navBar = [self.navigationController.navigationBar snapshotViewAfterScreenUpdates:YES];
    UIView *mainView = [self.view snapshotViewAfterScreenUpdates:YES];
    mainView.center = CGPointMake(mainView.center.x, mainView.center.y + navBar.frame.size.height);
    [intermediateController.view addSubview:navBar];
    [intermediateController.view addSubview:mainView];

    //two step presentation
    [self presentViewController:intermediateController animated:NO completion:^{
        [intermediateController presentViewController:navController animated:YES completion:nil];
    }];
}

次に、(提示されたモーダルから)閉じる時が来たら:

- (void)dismissMySelf
{
    //again - two step process to dismiss the this controller and the intermediate controller
    UIViewController *originalPresenter = self.presentingViewController.presentingViewController;
    [self.presentingViewController dismissViewControllerAnimated:YES completion:^{
        [originalPresenter dismissViewControllerAnimated:NO completion:nil];
    }];
}

スナップショットは静止画像であり、回転を処理しないため、微調整する必要がありましたが、一般的にはうまく機能しました。それが役に立てば幸い。

于 2014-02-28T18:44:14.397 に答える