web-dev-qa-db-fra.com

Les préférences d'UIViewControllerStatusBarHidden ne fonctionnent pas

J'essaie de masquer la barre d'état de l'un de mes contrôleurs de vue (lors de son affichage modal). Lorsque je présente le contrôleur de vue, la barre d'état doit être masquée, puis renvoyée en cas de licenciement.

J'ai ajouté le code suivant au contrôleur de vue présenté

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

J'ai également défini les clés du fichier Info.plist comme suit:

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

À ma connaissance, cela devrait suffire à faire ce travail. 

J'utilise également un contrôleur d'animation personnalisé pour faire la présentation conforme au protocole UIViewControllerAnimatedTransitioning. Dans l'implémentation animateTransition:, j'ai essayé d'appeler manuellement prefersStatusBarHidden, suivi de setNeedsStatusBarAppearanceUpdate pour s'assurer que l'appel est bien passé, mais la barre d'état reste.

Toute idée de ce qui se passe serait appréciée. J'ai effectué une recherche dans StackOverflow, mais il semble que personne n'ait eu ce problème. Toutes les réponses acceptées font référence à l'appel setNeedsStatusBarAppearanceUpdate, ce que je suis déjà en train de faire.

EDIT - Le code ci-dessous semble maintenant être WORK comme vous le souhaitez 

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

Dans iOS7, il existe en fait une nouvelle propriété pour UIViewController appelée modalPresentationCapturesStatusBarAppearance. Référence Apple iOS.

La valeur par défaut est NO.

Lorsque vous présentez un contrôleur de vue en appelant la méthode presentViewController: animated: complétion:, le contrôle de l'apparence de la barre d'état est transféré du contrôleur de présentation au contrôleur de vue présenté uniquement si la valeur modalPresentationStyle du contrôleur présenté est UIModalPresentationFullScreen. En définissant cette propriété sur YES, vous spécifiez l'apparence de la barre d'état des commandes du contrôleur de vue présentées, même si elles ne sont pas présentées en plein écran.

Le système ignore la valeur de cette propriété pour un contrôleur de vue présenté en plein écran.

Par conséquent, pour tout presentationStyle autre que le mode plein écran normal (par exemple: UIModalPresentationCustom), ce doit être défini sur si vous souhaitez capturer la barre d'état. Pour l'utiliser, tout ce que vous avez à faire est de le définir sur YES sur le contrôleur de vue qui est présenté:

toVC.modalPresentationCapturesStatusBarAppearance = YES;
106
David Liu

Je vais deviner (éclairé, mais toujours incertain) que c'est parce que lorsque vous faites un contrôleur de vue présenté en utilisant une transition personnalisée, dans iOS 7, l'ancien contrôleur de vue est toujours là. Par conséquent, il a probablement encore son mot à dire.

Vous pourriez même mettre un point d'arrêt dans itsprefersStatusBarHidden pour voir; vous devrez l'implémenter s'il ne l'est pas. La valeur par défaut est NON, donc si elle est consultée, cela expliquerait votre résultat.

Si j'ai raison, vous devrez implémenter la variable prefersStatusBarHidden de old view controller pour donner deux réponses différentes, selon que la variable presentedViewController est ou non.

EDITJe viens de confirmer cela. C'est encore pire que je pensais; lors de mes tests, la variable prefersStatusBarHidden du deuxième contrôleur de vue n'est pas appelée du tout. Le tout est entre les mains du premier contrôleur de vue. Cela a du sens car, comme je l’ai dit, le premier contrôleur de vue ne disparaît jamais; avec une animation de présentation personnalisée, le deuxième contrôleur de vue est subordonné au premier, car la deuxième vue peut survoler partiellement la première vue.

Ainsi, vous devrez piloter entièrement la barre d'état à partir du premier contrôleur de vue. Vous pouvez faire appeler sa prefersStatusBarHidden en appelant [self setNeedsStatusBarAppearanceUpdate]. Vous devrez donner une réponse différente selon les circonstances. Cela peut être un peu délicat. Voici une implémentation simple, mais qui peut ne pas couvrir tous les cas:

// 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

Vous pouvez ajouter ceci à info.plist

"Afficher l'apparence de la barre d'état basée sur le contrôleur" et définir la valeur sur "Non"

0
zuyao88