50

View Controllerの1つのステータスバーを非表示にしようとしています(モーダル表示の場合)。ビュー コントローラーを表示しているとき、ステータス バーは非表示になり、閉じたときに返されます。

提示されたView Controllerに次のコードを追加しました

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

また、Info.plist ファイルのキーを次のように設定しました。

<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

私の理解では、これがこの作業を行うために必要なすべてのはずです。

また、カスタム アニメーション コントローラーを使用して、UIViewControllerAnimatedTransitioningプロトコルに準拠したプレゼンテーションを行っています。実装では、animateTransition:手動で を呼び出しprefersStatusBarHidden、続いsetNeedsStatusBarAppearanceUpdateて呼び出しが行われていることを確認しようとしましたが、ステータス バーは残ります。

なぜこれが起こっているのかについてのアイデアをいただければ幸いです。私は StackOverflow を検索しましたが、誰もこの問題を抱えていないようです。受け入れられたすべての回答はsetNeedsStatusBarAppearanceUpdate、私がすでに行っている呼び出しを参照しています。

編集- 以下のコードは、希望どおりに機能するようになりました

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    if (self.isPresenting) {
        UIView *containerView = [transitionContext containerView];

        UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

        toViewController.view.frame = containerView.frame;

        [containerView addSubview:toViewController.view];

        // Ask the presented controller whether to display the status bar
        [toViewController setNeedsStatusBarAppearanceUpdate];

        [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
            toViewController.view.alpha = 1.0f;
            fromViewController.view.alpha = 0.0f;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    else {
        // do the reverse
        UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

        [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
            toViewController.view.alpha = 1.0f;
            fromViewController.view.alpha = 0.0f;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
            // Once dismissed - ask the presenting controller if the status bar should be presented
            [toViewController setNeedsStatusBarAppearanceUpdate];
        }];
    }
}

....

// PresentingController.m
- (BOOL)prefersStatusBarHidden
{
    if (self.presentedViewController) {
        return YES;
    }
    return NO;
}

// PresentedController.m
- (BOOL)prefersStatusBarHidden
{
    return YES;
}
4

4 に答える 4

129

iOS7 では、実際には UIViewController と呼ばれる新しいプロパティがありますmodalPresentationCapturesStatusBarAppearanceApple iOS リファレンス。

デフォルト値は NO です。

presentViewController:animated:completion: メソッドを呼び出してビュー コントローラーを提示すると、提示されたコントローラーの modalPresentationStyle 値が UIModalPresentationFullScreen である場合にのみ、ステータス バーの外観コントロールが提示元から提示されたビュー コントローラーに転送されます。このプロパティを YES に設定すると、非フルスクリーンで表示される場合でも、表示されるビュー コントローラー コントロールのステータス バーの外観を指定できます。

フルスクリーンで表示されるView Controllerの場合、システムはこのプロパティの値を無視します。

したがって、通常のフルスクリーン以外のすべての presentationStyle (例: UIModalPresentationCustom) の場合、ステータス バーをキャプチャする場合はこれを設定する必要があります。YES使用するには、提示されているView Controllerで設定するだけです:

toVC.modalPresentationCapturesStatusBarAppearance = YES;
于 2014-08-15T21:31:07.910 に答える
17

これは、iOS 7 でカスタム トランジションを使用して提示されたビュー コントローラーを実行すると、古いビュー コントローラーがまだ存在するためであると推測します (教育を受けていますが、まだ推測です) 。したがって、おそらくまだ発言権があります。

ブレークポイントを設定して表示することもできます prefersStatusBarHidden。実装されていない場合は実装する必要があります。デフォルトは NO です。それを参照すれば、結果が説明されます。

私が正しければ、古いView Controllerを実装prefersStatusBarHiddenして、aがあるかどうかに応じて2つの異なる答えを出す必要がありpresentedViewControllerます。

編集私は今これを確認しました。思ったよりも悪いです。私のテストでは、2 番目のビュー コントローラーprefersStatusBarHiddenはまったく呼び出されていません。全体は最初のView Controllerの手に委ねられています。これは理にかなっています。なぜなら、最初のビュー コントローラーがなくなることはないからです。カスタム プレゼンテーション アニメーションでは、2 番目のビューが最初のビューの上に部分的に移動できるため、2 番目のビュー コントローラーは最初のビュー コントローラーに従属します。

したがって、最初のビュー コントローラーからステータス バーを完全に操作する必要があります。prefersStatusBarHiddenを呼び出すことで、それを呼び出すことができます[self setNeedsStatusBarAppearanceUpdate]。状況に応じて、異なる回答をする必要があります。これは少し難しいかもしれません。以下は単純な実装ですが、すべてのケースをカバーしているとは限りません。

// ViewController1:

-(void)setHide:(NSNumber*)yn {
    self->hide = [yn boolValue]; // a BOOL ivar
    [self setNeedsStatusBarAppearanceUpdate];
}
-(BOOL)prefersStatusBarHidden {
    return self->hide;
}
- (IBAction)doButton:(id)sender {
    self->hide = YES;
    [self setNeedsStatusBarAppearanceUpdate];
    [self presentViewController:[ViewController2 new] animated:YES completion:nil];
}

// ==========

// ViewController2:

- (IBAction)doButton:(id)sender {
    [self.presentingViewController setValue:NO forKey:@"hide"];
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
于 2014-05-12T19:08:43.583 に答える