web-dev-qa-db-fra.com

UIStatusBarStyle PreferredStatusBarStyle ne fonctionne pas sur iOS 7

Dans mon application iPhone construite avec Xcode 5 pour iOS 7, j'ai défini UIViewControllerBasedStatusBarAppearance=YES dans info.plist, et dans mon ViewController j'ai ce code:

-(UIStatusBarStyle) preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

Mais la barre d'état est toujours noire sur le fond noir.

Je sais qu'il est possible de changer cette application en définissant UIViewControllerBasedStatusBarAppearance=NO dans info.plist, mais je dois en fait modifier cela viewController de viewController à l'exécution.

107
Andrew Smith

OK, voici le truc. Vous devez ajouter la clé "Afficher la barre d'état basée sur le contrôleur" et définir la valeur sur Non.

Ceci est contraire à la signification apparente de cette clé, mais même si vous définissez la valeur sur No, vous pouvez toujours modifier l'apparence de la barre d'état, qu'elle soit affichée ou non dans un contrôleur de vue. . Donc, il agit comme "Oui" mais réglez-le sur "Non"!

Maintenant, je peux obtenir la barre d'état blanche ou sombre.

86
Andrew Smith

J'ai découvert que si votre ViewController est à l'intérieur d'un navigationController, alors le navigationBar.barStyle détermine le statusBarStyle.

Régler le paramètre barStyle de votre barre de navigation sur UIBarStyleBlackTranslucent donnera un texte de barre d'état blanche (c'est-à-dire UIStatusBarStyleLightContent) et UIBarStyleDefault donnera un texte de barre d'état noire (c'est-à-dire UIStatusBarStyleDefault).

Note Cela s’applique même si vous changez totalement la couleur de la barre de navigation via son barTintColor.

278
mxcl

Pour que preferredStatusBarStyle() fonctionne dans UINavigationController et UITabBarController, j'ajoute le code suivant, qui obtiendra le style de barre d'état préféré du contrôleur de vue actuellement visible.

extension UITabBarController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return visibleViewController
    }
}

Pour Swift ce ne sont pas des méthodes mais des propriétés:

extension UITabBarController {
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return visibleViewController
    }
}

Les propriétés Swift 4.2 ont été renommées:

extension UITabBarController {
   open override var childForStatusBarStyle: UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
   open override var childForStatusBarStyle: UIViewController? {
        return visibleViewController
    }
}

tilisation

class ViewController: UIViewController {

    // This will be called every time the ViewController appears
    // Works great for pushing & popping
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

}
72
Daniel Wood

J'arrive peut-être un peu tard, mais si quelqu'un d'autre cherchait une solution efficace et vérifiée au niveau de l'application.

@mxcl décrit correctement pourquoi cela se produit. Afin de le corriger, nous créons simplement une extension (ou une catégorie dans obj-c) qui remplace la méthode preferredSatusBarStyle () de UINavigationController. Voici un exemple dans Swift:

extension UINavigationController {
    public override func preferredStatusBarStyle() -> UIStatusBarStyle {
        if let rootViewController = self.viewControllers.first {
            return rootViewController.preferredStatusBarStyle()
        }
        return super.preferredStatusBarStyle()
    }
}

Ce code extrait simplement le premier contrôleur de vue (le contrôleur de vue racine) et le décompresse (dans obj-c, vérifiez simplement qu'il n'est pas nul). Si le déroulement est réussi (et non nul), nous récupérons le rootViewControllers preferredStatusBarStyle. Sinon, nous renvoyons simplement la valeur par défaut.

J'espère que cela aidera tous ceux qui pourraient en avoir besoin.

33
Kyle Begeman

Pour fournir plus de détails dans la réponse acceptée, insérez la ligne suivante dans la méthode didFinishLaunchingWithOptions: Du délégué de votre application:

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;

Ensuite, dans votre Info.plist, ajoutez View controller-based status bar appearance Et définissez-le sur NO.

Je crois que c'est comme cela que cela devrait être fait, PAS à partir du contrôleur de navigation, si vous voulez la même couleur de barre d'état pour l'ensemble de l'application. Vous avez peut-être des écrans qui ne sont pas nécessairement intégrés à une UINavigationController, ou une autre sous-classe UINavigationController, et ailleurs.

[~ # ~] edit [~ # ~] : Vous pouvez également le faire sans saisir de code: https: // stackoverflow. com/a/18732865/85568

21
Matthew Quiros

Dans viewDidLoad, écrivez simplement ceci

[self setNeedsStatusBarAppearanceUpdate];

faites juste ça et ça marchera

pouvez-vous s'il vous plaît essayer cela

Set UIViewControllerBasedStatusBarAppearance to NO.
Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

Une dernière chose que j'ai vue dans votre question, c'est que vous avez écrit la méthode comme celle-ci.

 -(void)UIStatusBarStyle PreferredStatusBarStyle ()
        {
            return UIStatusBarStyle.LightContent;
        }

mais ça devrait être comme ça

-(UIStatusBarStyle)preferredStatusBarStyle{ 
    return UIStatusBarStyleLightContent; 
} 
10
User 1531343

Voici comment je l'ai résolu. Ce sont généralement les navigateursContrôleur ou TabBarController qui décident de l’aspect de la barre d’état (masqué, couleur, etc.).

Je me suis donc retrouvé à sous-classer le contrôleur de navigation et à redéfinir preferredStatusBarStyle. si le ViewContorller visible actuel implémente StatusBarStyleHandler, je demande que la valeur soit utilisée comme style, sinon je retourne une valeur par défaut.

Pour déclencher une mise à jour de l'apparence de la barre d'état, appelez setNeedsStatusBarAppearanceUpdate, ce qui déclenche à nouveau preferredStatusBarStyle et met à jour l'interface utilisateur en fonction des informations renvoyées par la méthode.

public protocol StatusBarStyleHandler {
    var preferredStatusBarStyle: UIStatusBarStyle { get }
}

public class CustomNavigationCotnroller: UINavigationController {

    public override var preferredStatusBarStyle: UIStatusBarStyle {
        if let statusBarHandler = visibleViewController as? StatusBarStyleHandler {
            return statusBarHandler.preferredStatusBarStyle
        }

        return .default
    }
}

Puis utilisation

public class SomeController: UIViewController, StatusBarStyleHandler {

    private var statusBarToggle = true

    // just a sample for toggling the status bar style each time method is called
    private func toggleStatusBarColor() {
        statusBarToggle = !statusBarToggle
        setNeedsStatusBarAppearanceUpdate()
    }

    public override var preferredStatusBarStyle: UIStatusBarStyle {
        return statusBarToggle ? .lightContent : .default
    }
}
5
aryaxt

Même avec toutes les réponses ici je n'ai toujours pas trouvé la solution exacte pour moi, mais a commencé avec la réponse de Daniel. Ce que j'ai fini par être:

override var preferredStatusBarStyle: UIStatusBarStyle {
     return visibleViewController?.preferredStatusBarStyle ?? .lightContent
}

dans les contrôleurs de navigation (similaire pour onglet, juste selectedViewController). Et puis il respectera le:

override var preferredStatusBarStyle: UIStatusBarStyle {
     return .lightContent
}

Dans chaque contrôleur de vue, sauf indication contraire de votre part. Je n'ai pas besoin d'appeler setNeedsStatusBarAppearanceUpdate() n'importe où, il se met simplement à jour lorsque vous arrivez à chaque contrôleur de vue.

4
Andrew Plummer

1) Un paramètre pour l'ensemble du projet:

Si disponible, supprimez UIViewControllerBasedStatusBarAppearance la paire clé-valeur de votre info.plist ou définissez NO sans la supprimer. Si ce n'est pas disponible dans votre info.plist, ne faites rien. La valeur par défaut est NO pour cette propriété.

Ajoutez le code ci-dessous à votre AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

2) Paramètres différents pour différents contrôleurs de vue:

Ajoutez la paire UIViewControllerBasedStatusBarAppearance à votre info.plist et réglez-la sur YES.

Si votre View Controller n'est pas intégré au contrôleur de navigation. Disons MyViewController. ajoutez simplement le code ci-dessous à votre fichier MyViewController.m. Si votre contrôleur de vue est intégré au contrôleur de navigation, créez une nouvelle classe Cocoa Touch et faites-en une sous-classe de UINavigationController. Disons MyNC. Sélectionnez la vue Contrôleur de navigation sur votre Storyboard, dans le volet de droite; Utilitaires -> Inspecteur d'identité -> Classe personnalisée -> Classe, tapez "MyNC". Après avoir lié la vue Storyboard à votre classe "MyNC" Cocoa Touch, ajoutez le code ci-dessous à votre MyNC.m:

- (BOOL)prefersStatusBarHidden {
    return NO;
}

-(UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}
3
Fatih Aksu

Swift 4.2

extension UITabBarController {
    open override var childForStatusBarStyle: UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    open override var childForStatusBarStyle: UIViewController? {
        return visibleViewController
    }
}
2
Vyacheslav

Si vous utilisez NavigationController, vous pouvez sous-classer NavigationController pour qu'il consulte son contrôleur de vue enfant.

// MyCustomNavigationController

- (NSUInteger)supportedInterfaceOrientations {
    UIViewController *viewControllerToAsk = [self findChildVC];
    return [viewControllerToAsk supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotate {
    UIViewController *viewControllerToAsk = [self findChildVC];
    return [viewControllerToAsk shouldAutorotate];
}

- (UIStatusBarStyle)preferredStatusBarStyle {
    UIViewController *viewControllerToAsk = [self findChildVC];
    return [viewControllerToAsk preferredStatusBarStyle];
}

- (UIViewController *)findChildVC {
    return self.viewControllers.firstObject;
}
1
onmyway133

Exemple rapide

dans AppDelegate.Swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent;

    return true
}

dans info.plist définir l'affichage de l'apparence de la barre d'état basée sur le contrôleur: NON

1
fyalavuz

Si dans le cas où vous vouliez masquer la barre de statut pendant splashScreen mais que vous vouliez changer le style en contenu clair (StatusBarInitiallyHidden sur Plist doit être NON pour masquer la barre de statut sur splash), vous pouvez l'ajouter à la méthode didFinishLaunchingWithOptions d'appDelegate pour la remplacer par lightContent.

[[UIApplication sharedApplication]setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
1
aalesano

Vous pouvez définir le style de la barre d'état. Elle ressemblera à la barre d’état telle que IOS 6 et moins.
Collez cette méthode dans votre contrôleur de vue

-(UIStatusBarStyle)preferredStatusBarStyle{
    return UIStatusBarStyleBlackOpaque;
}

et appelez cette méthode de vue ne charge comme ça

if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
       [self setNeedsStatusBarAppearanceUpdate];
    }
0
Ganapathy

Je veux juste ajouter une note pour un cas spécifique que j'ai rencontré. J'avais une autre UIWindow dans mon application pour afficher un visage de discussion flottant dans mon application tout le temps. Faire cela n'a causé aucune des solutions ci-dessus, et je ne sais pas trop pourquoi! Tout ce que j'ai remarqué, c'est que mon ViewController dans la nouvelle UIWindow en était la raison! Et si je veux changer le style de la barre d'état, je dois le faire dans le contrôleur de vue de la nouvelle UIWindow.

Cette note pourrait aider d'autres personnes ayant une structure similaire! Donc, fondamentalement, vous pouvez appliquer les solutions mentionnées ci-dessus dans le ViewController de la nouvelle UIWindow.

Encore une fois c'est un cas spécifique.

Merci

0
Ehab Saifan