web-dev-qa-db-ja.com

UIViewControllerのprefersStatusBarHiddenが機能しない

View Controllerの1つのステータスバーを非表示にしようとしています(モーダル表示時)。 View Controllerを表示しているとき、ステータスバーは非表示になり、終了すると戻ります。

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

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

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

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

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

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

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

[〜#〜] edit [〜#〜]-以下のコードは、今では[〜#〜] work [〜#〜]必要に応じて

- (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;
}
43
Taz

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

デフォルト値はNOです。

PresentViewController:animated:completion:メソッドを呼び出してView Controllerを提示すると、提示されたControllerのmodalPresentationStyle値がUIModalPresentationFullScreenの場合にのみ、ステータスバーの外観制御が提示から提示されたView Controllerに転送されます。このプロパティをYESに設定することにより、フルスクリーンではない場合でも、表示されるView Controllerコントロールのステータスバーの外観を指定します。

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

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

toVC.modalPresentationCapturesStatusBarAppearance = YES;
113
David Liu

これは、iOS 7でカスタムトランジションを使用して表示されたView Controllerを実行するとき、古いView Controllerがまだ存在しているためだと推測します。したがって、おそらくまだ発言権があります。

ブレークポイントをitsprefersStatusBarHiddenに入れて見ることもできます。実装されていない場合は実装する必要があります。デフォルトはNOであるため、参照した場合、結果が説明されます。

私が正しい場合は、oldView ControllerのprefersStatusBarHiddenを実装して、それがあるかどうかに応じて2つの異なる答えを与える必要がありますpresentedViewControllerかどうか。

[〜#〜] edit [〜#〜]これで確認しました。それは私が思ったよりもさらに悪い。私のテストでは、2番目のView ControllerのprefersStatusBarHiddenはまったく呼び出されていません。すべては、最初のView Controllerの管理下にあります。私が言ったように、最初のView Controllerがなくなることはないため、これは理にかなっています。カスタムプレゼンテーションアニメーションでは、2番目のビューコントローラーが最初のビューコントローラーに従属します。これは、2番目のビューが最初のビューの上に部分的にホバーできるためです。

したがって、最初のView Controllerから完全にステータスバーを操作する必要があります。 [self setNeedsStatusBarAppearanceUpdate]を呼び出すことにより、prefersStatusBarHiddenを呼び出すことができます。状況に応じて異なる回答をする必要があります。これには少し注意が必要です。簡単な実装を次に示しますが、すべてのケースを網羅しているわけではありません。

// 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];
}
17
matt

動作せず、UIViewControllerがUINavigationControllerの子である場合、このコードが解決策になる可能性があります。

open override var prefersStatusBarHidden: Bool {
    return topViewController?.prefersStatusBarHidden ?? super.prefersStatusBarHidden
}

基本的に、UINavigationControllerは独自のprefersStatusBarHidden値を使用しますが、私の場合は、階層内のトップビューコントローラーのプロパティでそれを上書きしたかったのです。

0
Konrad Siemczyk

これをinfo.plistに追加できます

「コントローラーベースのステータスバーの外観を表示」および値を「いいえ」に設定

0
zuyao88