La barre d'état iOS 7 revient au style par défaut iOS 6 dans l'application iPhone?

292

Dans iOS 7, le UIStatusBara été conçu de manière à fusionner avec la vue comme ceci:

Interface graphique conçue par Tina Tavčar (GUI conçue par Tina Tavčar )

  • C'est cool, mais cela va un peu gâcher votre vue lorsque vous avez quelque chose dans la partie supérieure de votre vue, et il se chevauche avec la barre d'état.

  • Existe-t-il une solution simple (telle que la définition d'une propriété dans info.plist) qui peut changer la façon dont cela fonctionne [sans se chevaucher] pour revenir à ce qu'elle est dans iOS6?

  • Je sais qu'une solution plus simple consiste à avoir self.view.center.x+ 20 points pour chaque contrôleur de vue unique, mais les changer va bousiller d'autres dimensions (avoir un autre self.view.center.xpeut causer des problèmes aux séquences personnalisées, etc.) et soudain, cela se transforme en un travail fastidieux qui est à éviter.

  • Je serai vraiment heureux si quelqu'un peut me fournir une solution à un revêtement pour cela.

PS Je sais que je peux cacher la barre d'état en faisant des choses comme avoir

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

Dans la didFinishLaunchingWithOptionsméthode, mais c'est une solution de contournement, un raccourci évitant le problème, donc je ne considère pas que c'est une vraie solution.

吖 奇 说 - 何魏奇 Archy le fera-t-il
la source
6
Malheureusement, les barres d'état noires ont été dépréciées dans iOS 7
i_duhh_bomb
Je vais être d'accord avec @GangstaGraham. Ces couleurs sont tout simplement magnifiques ! Pour répondre à votre question, je crains que vous ne puissiez pas. La raison pour laquelle la barre d'état est conçue comme ça maintenant est que la translucidité est la nouvelle chose iOS et elle est conçue pour donner de la "profondeur" à une application en disant qu'elle est au-dessus de quelque chose, donc il y a quelque chose en dessous.
Cole Johnson
Avez-vous essayé de définir PreferredStatusBarStyle sur UIStatusBarDefault? Checkout iOS 7 Documentation UIViewController
theaob
1
La présence UIStatusBarDefaultde la barre d'état ne fait que rendre son contenu de couleur noire. Cela ne reviendra pas à la façon dont il fonctionne dans iOS6.
吖 奇 说 - 何魏奇 Archy Will He
2
Une chance avec ça? J'adore iOS7 mais cette chose me rend fou!
Mihai Fratu

Réponses:

449

Ceci est une publication croisée d' un article de blog que j'ai écrit , mais voici un aperçu complet des barres d'état, des barres de navigation et des contrôleurs de vue de conteneur sur iOS 7:

  1. Il n'y a aucun moyen de conserver la disposition de la barre d'état de style iOS 6. La barre d'état chevauchera toujours votre application sur iOS 7

  2. Ne confondez pas l'apparence de la barre d'état avec la disposition de la barre d'état. L'apparence (claire ou par défaut) n'affecte pas la disposition de la barre d'état (cadre / hauteur / chevauchement). Il est également important de noter que la barre d'état du système n'a plus de couleur d'arrière-plan. Lorsque l'API fait référence à UIStatusBarStyleLightContent, cela signifie du texte blanc sur un fond clair. UIStatusBarStyleDefault est un texte noir sur fond clair.

  3. L'apparence de la barre d'état est contrôlée le long de l'un des deux chemins de base mutuellement exclusifs: vous pouvez soit les définir par programme de la manière traditionnelle, soit UIKit mettra à jour l'apparence pour vous en fonction de certaines nouvelles propriétés de UIViewController. Cette dernière option est activée par défaut. Vérifiez la valeur de plist de votre application pour «Apparence de la barre d'état basée sur ViewController» pour voir celle que vous utilisez. Si vous définissez cette valeur sur YES, chaque contrôleur de vue de niveau supérieur de votre application (autre qu'un contrôleur de vue de conteneur UIKit standard) doit remplacer la propriété PreferredStatusBarStyle, en renvoyant le style par défaut ou le style léger. Si vous modifiez la valeur plist sur NO, vous pouvez gérer l'apparence de la barre d'état à l'aide des méthodes UIApplication connues.

  4. UINavigationController modifiera la hauteur de son UINavigationBar à 44 points ou 64 points, en fonction d'un ensemble de contraintes plutôt étrange et non documenté. Si UINavigationController détecte que le haut du cadre de sa vue est visuellement contigu avec le haut de son UIWindow, il dessine sa barre de navigation avec une hauteur de 64 points. Si le sommet de sa vue n'est pas contigu au sommet de l'UIWindow (même s'il n'est décalé que d'un seul point), il dessine sa barre de navigation de la manière «traditionnelle» avec une hauteur de 44 points. Cette logique est exécutée par UINavigationController même s'il y a plusieurs enfants dans la hiérarchie du contrôleur de vue de votre application. Il n'existe aucun moyen d'empêcher ce comportement.

  5. Si vous fournissez une image d'arrière-plan de barre de navigation personnalisée qui ne mesure que 44 points (88 pixels) et que les limites de la vue de UINavigationController correspondent aux limites de UIWindow (comme expliqué au point 4), UINavigationController dessinera votre image dans le cadre (0,20,320 , 44), laissant 20 points d'espace noir opaque au-dessus de votre image personnalisée. Cela peut vous amener à penser que vous êtes un développeur intelligent qui a contourné la règle n ° 1, mais vous vous trompez. La barre de navigation mesure toujours 64 points. L'incorporation d'un UINavigationController dans une hiérarchie de vues de style diapositive-à-révéler rend cela très clair.

  6. Méfiez-vous de la propriété edgeForExtendedLayout nommée avec confusion de UIViewController. L'ajustement des bords ForExtendedLayout ne fait rien dans la plupart des cas. La seule façon dont UIKit utilise cette propriété est si vous ajoutez un contrôleur de vue à un UINavigationController, puis l'UINavigationController utilise bordsForExtendedLayout pour déterminer si son contrôleur de vue enfant doit être visible sous la barre de navigation / zone de barre d'état. La définition de edgeForExtendedLayout sur l'UINavigationController lui-même ne change rien au fait que l'UINavigationController possède ou non une zone de barre de navigation haute de 44 ou 64 points. Voir # 4 pour cette logique. Une logique de disposition similaire s'applique au bas de votre vue lorsque vous utilisez une barre d'outils ou UITabBarController.

  7. Si tout ce que vous essayez de faire est d'empêcher votre contrôleur de vue enfant personnalisé de sous-chevaucher la barre de navigation lorsqu'il est à l'intérieur d'un UINavigationController, définissez bordsForExtendedLayout sur UIRectEdgeNone (ou au moins un masque qui exclut UIRectEdgeTop). Définissez cette valeur le plus tôt possible dans le cycle de vie de votre contrôleur de vue.

  8. UINavigationController et UITabBarController essaieront également de remplir les contentInsets des vues de table et des vues de collection dans sa hiérarchie de sous-vues. Il le fait d'une manière similaire à la logique de la barre d'état de # 4. Il existe un moyen par programme d'empêcher cela, en définissant automatiquementAdjustsScrollViewInsets sur NO pour vos vues de table et vues de collection (il est par défaut YES). Cela a posé de sérieux problèmes pour Whisper et Riposte, car nous utilisons des ajustements contentInset pour contrôler la disposition des vues de table en réponse aux mouvements de la barre d'outils et du clavier.

  9. Pour réitérer: il n'y a aucun moyen de revenir à la logique de disposition de la barre d'état de style iOS 6. Pour approximer cela, vous devez déplacer tous les contrôleurs de vue de votre application dans une vue de conteneur décalée de 20 points du haut de l'écran, laissant une vue intentionnellement noire derrière la barre d'état pour simuler l'ancienne apparence. C'est la méthode que nous avons finalement utilisée dans Riposte et Whisper.

  10. Apple met tout en œuvre pour que vous n'essayiez pas de faire # 9. Ils veulent que nous remodelions toutes nos applications pour sous-chevaucher la barre d'état. Cependant, il existe de nombreux arguments convaincants, à la fois pour l'expérience utilisateur et pour des raisons techniques, pourquoi ce n'est pas toujours une bonne idée. Vous devez faire ce qui est le mieux pour vos utilisateurs et ne pas simplement suivre la fantaisie de la plate-forme.

jaredsinclair
la source
35
Je voulais juste ajouter que vous pouvez ajouter une contrainte à tout ce qui se trouve en haut de votre vue pour être attaché au guide de mise en page supérieur - cela laissera un espace vide derrière la barre d'état (que vous pouvez remplir avec la couleur de votre choix) mais permettra également à la vue de s'ajuster automatiquement à la position correcte dans iOS 6. De cette façon, vous n'avez pas à ajuster manuellement la position de vos vues dans le code.
BreadicalMD
4
Voilà une solution brillante. Vous avez révélé mon ignorance sur AutoLayout. Mieux vaut y aller.
jaredsinclair
1
Si vous placez l'espace supérieur de votre objet sous le bord du guide de présentation supérieur, vous pouvez utiliser le contrôle de contrainte pour ajouter une contrainte d'espacement vertical au voisin le plus proche, qui sera désormais le guide de présentation supérieur. Vous pouvez également utiliser ctrl + clic de votre objet vers le guide de mise en page supérieur pour ajouter explicitement une contrainte d'espacement vertical.
BreadicalMD
2
@BreadicalMD Une partie que je ne comprends pas est que -topLayoutGuide n'est pas disponible sur iOS 6, donc cela signifie-t-il que vous devez utiliser différentes contraintes de disposition automatique sur iOS 7 et 6?
Jeremy
1
Excellente réponse ... Mais j'ai un doute 1) UINavigationController modifiant la partie en hauteur.Veuillez l'expliquer un peu plus. merci
user1010819
122

Mises à jour du 19 septembre 2013:

correction des bogues de mise à l'échelle en ajoutant self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);

fautes de frappe corrigées dans la NSNotificationCenterdéclaration


Mises à jour du 12 septembre 2013:

corrigé UIViewControllerBasedStatusBarAppearanceàNO

ajouté une solution pour les applications avec rotation d'écran

ajouté une approche pour changer la couleur d'arrière-plan de la barre d'état.


Il n'y a apparemment aucun moyen de ramener la barre d'état iOS7 à son fonctionnement dans iOS6.

Cependant, nous pouvons toujours écrire des codes et transformer la barre d'état en iOS6, et c'est le moyen le plus court que je puisse trouver:

  1. Défini UIViewControllerBasedStatusBarAppearancesur NOin info.plist(pour désactiver la possibilité pour les contrôleurs de vue d'ajuster le style de la barre d'état afin que nous puissions définir le style de la barre d'état à l'aide de la méthode UIApplicationstatusBarStyle.)

  2. Dans AppDelegate application:didFinishLaunchingWithOptions, appelez

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        [application setStatusBarStyle:UIStatusBarStyleLightContent];
        self.window.clipsToBounds =YES;
        self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
    
        //Added on 19th Sep 2013
        self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
    }
    return YES;
    


afin de:

  1. Vérifiez si c'est iOS 7.

  2. Définissez le contenu de la barre d'état sur blanc, par opposition à UIStatusBarStyleDefault.

  3. Évitez que les sous-vues dont les images s'étendent au-delà des limites visibles ne s'affichent (pour les vues animées dans la vue principale depuis le haut).

  4. Créez l'illusion que la barre d'état prend de la place comme dans iOS 6 en déplaçant et en redimensionnant le cadre de la fenêtre de l'application.


Pour les applications avec rotation d'écran,

utiliser NSNotificationCenter pour détecter les changements d'orientation en ajoutant

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidChangeStatusBarOrientation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];

dans if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)et créez une nouvelle méthode dans AppDelegate:

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
    int a = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
    int w = [[UIScreen mainScreen] bounds].size.width;
    int h = [[UIScreen mainScreen] bounds].size.height;
    switch(a){
        case 4:
            self.window.frame =  CGRectMake(0,20,w,h);
            break;
        case 3:
            self.window.frame =  CGRectMake(-20,0,w-20,h+20);
            break;
        case 2:
            self.window.frame =  CGRectMake(0,-20,w,h);
            break;
        case 1:
           self.window.frame =  CGRectMake(20,0,w-20,h+20);
    }
}

De sorte que lorsque l'orientation change, il déclenche une instruction de commutation pour détecter l'orientation de l'écran de l'application (Portrait, à l'envers, paysage gauche ou paysage droit) et modifier le cadre de la fenêtre de l'application respectivement pour créer l'illusion de la barre d'état iOS 6.


Pour modifier la couleur d'arrière-plan de votre barre d'état:

Ajouter

 @property (retain, nonatomic) UIWindow *background;

en AppDelegate.hpour faire backgroundune propriété dans votre classe et empêcher l' ARC de désaffecter il. (Vous n'êtes pas obligé de le faire si vous n'utilisez pas ARC.)

Après cela, il vous suffit de créer l'interface utilisateur dans if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) :

background = [[UIWindow alloc] initWithFrame: CGRectMake(0, 0, self.window.frame.size.width, 20)];
background.backgroundColor =[UIColor redColor];
[background setHidden:NO];

N'oubliez pas @synthesize background;après @implementation AppDelegate!

吖 奇 说 - 何魏奇 Archy le fera-t-il
la source
3
Cela rompt avec la rotation. juste un
avertissement
2
@JesseNaugher Je recommande de modifier par programme la contrainte d'espacement vertical de 0 à 20. Cela fonctionnera sur la rotation.
expert
2
Une idée sur la façon d'éviter que la barre de navigation s'agrandisse de 20 pixels? Cette solution me convient, mais ma barre de navigation est trop haute de 20 pixels.
simonbs
4
@ArchyHolt: Votre solution simple fonctionne pour moi, sauf lorsque je présente un contrôleur de vue modale. Une fois que le contrôleur de vue modale est fermé, la vue restante est maintenant sous la barre d'état. J'ai reproduit cela dans un nouveau projet d'échantillon pour m'assurer qu'il n'y a rien d'autre de funky en cours. Je pense que votre solution plus avancée pourrait être utile ici, mais je ne sais pas quelle notification entrerait en jeu. Des idées?
markdorison
4
La vue est réinitialisée après la fermeture d'un contrôleur de vue modale. :(
KarenAnne
41

MISE À JOUR (NOUVELLE SOLUTION)

Cette mise à jour est la meilleure solution au problème de la barre de navigation iOS 7. Vous pouvez définir l'exemple de couleur de la barre de navigation: FakeNavBar.backgroundColor = [UIColor redColor];

Remarque: Si vous utilisez le contrôleur de navigation par défaut, veuillez utiliser l'ancienne solution.

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if(NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0)
    {
        UIView *FakeNavBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
        FakeNavBar.backgroundColor = [UIColor whiteColor];

        float navBarHeight = 20.0;
        for (UIView *subView in self.window.subviews) {

            if ([subView isKindOfClass:[UIScrollView class]]) {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height - navBarHeight);
            } else {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height);
            }
        }
        [self.window addSubview:FakeNavBar];
    }

    return YES;

}

ANCIENNE SOLUTION - SI vous utilisez le code précédent, veuillez ignorer le code et l'image suivants

Il s'agit de l'ancienne version de la solution de barre de navigation iOS 7.

J'ai résolu le problème avec le code suivant. C'est pour ajouter une barre d'état. didFinishLaunchingWithOptions

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    UIView *addStatusBar = [[UIView alloc] init];
    addStatusBar.frame = CGRectMake(0, 0, 320, 20);
    addStatusBar.backgroundColor = [UIColor colorWithRed:0.973 green:0.973 blue:0.973 alpha:1]; //change this to match your navigation bar
    [self.window.rootViewController.view addSubview:addStatusBar];
}

Et pour Interface Builder, c'est pour quand vous ouvrez avec iOS 6; il commence à 0 pixels.

Remarque: les deltas iOS 6/7 n'apparaissent que si vous décochez "Utiliser la mise en page automatique" pour le contrôleur de vue dans "l'inspecteur de fichiers" (icône la plus à gauche) dans le volet de détails.

Entrez la description de l'image ici

İbrahim Özbölük
la source
6
Vous avez fait ma journée. Prenez +1 pour l'aide!
Niru Mukund Shah
5
Remarque: les deltas iOS 6/7 n'apparaissent que si vous décochez "Utiliser la mise en page automatique" pour le contrôleur de vue dans "l'inspecteur de fichiers" (icône la plus à gauche) dans le volet de détails.
Matt
1
Merci beaucoup! Tu m'as sauvé beaucoup d'ennuis!
neowinston
2
Qui a dit que la disposition de la barre d'état de style iOS 6 ne pouvait pas être maintenue, vous pouvez le faire par @ TacettinÖzbölük ... merci mec pour cette solution awsum.
Vizllx
1
joli! aussi, juste pour noter qu'Apple préfère maintenant: if (NSFoundationVersionNumber> = NSFoundationVersionNumber_iOS_6_1) {}
Joel Balmer
26

SOLUTION :

Définissez-le dans votre viewcontroller ou dans rootviewcontroller en remplaçant la méthode:

-(BOOL) prefersStatusBarHidden
    {
        return YES;
    }
Dave
la source
Pas une mauvaise solution. Retirez complètement la barre. Pourrait ne pas être idéal pour UX tout le temps mais réalisable.
Farhan Hafeez
Tout simplement génial. A parfaitement fonctionné pour moi.
madLokesh du
Scénario: Une fois que je reviens à mon UIVIew après avoir lu la vidéo en plein écran, une barre noire apparaît en bas qui est juste la taille de la barre d'état, bien que j'utilisais déjà une barre d'état. J'ai complètement supprimé la barre d'état et maintenant le problème est résolu.
madLokesh
J'ai seulement réussi à utiliser cette méthode
user2277872
17

Voici une autre approche pour les projets qui utilisent largement le Storyboard:

OBJECTIF:

Le but de cette approche est de recréer le même style de barre d'état dans iOS7 que dans iOS6 (voir le titre de la question "Barre d'état iOS 7 Retour au style iOS 6?").

RÉSUMÉ:

Pour ce faire, nous utilisons le Storyboard autant que possible en déplaçant les éléments d'interface utilisateur qui se chevauchent par la barre d'état (sous iOS 7) vers le bas, tout en utilisant des deltas pour annuler le changement de disposition vers le bas pour iOS 6.1 ou antérieur. L'espace supplémentaire résultant dans iOS 7 est ensuite occupé par une UIView avec le backgroundColor défini sur une couleur de notre choix. Ce dernier peut être créé en code ou en utilisant le Storyboard (voir ALTERNATIVES ci-dessous)

HYPOTHÈSES:

Pour obtenir le résultat souhaité en suivant les étapes ci-dessous, il est supposé qu'il View controller-based status bar appearanceest défini sur NO et que votre Status bar styleest défini sur "Style noir transparent (alpha de 0,5)" ou "Style noir opaque". Les deux paramètres peuvent être trouvés / ou ajoutés sous "Info" dans les paramètres de votre projet.

PAS:

  • Ajoutez une sous-vue à la fenêtre d'interface utilisateur pour servir d'arrière-plan à la barre d'état. Pour ce faire, ajoutez ce qui suit à votre AppDelegate application: didFinishLaunchingWithOptions:aprèsmakeKeyAndVisible

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        UIView *statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourAppsUIWindow.frame.size.width, 20)];
        statusBarBackgroundView.backgroundColor = [UIColor blackColor];
        [yourAppsUIWindow addSubview:statusBarBackgroundView];
    }
    
  • Étant donné que vous avez ajouté par programmation un arrière-plan pour iOS 7 UNIQUEMENT, vous devrez ajuster la disposition de vos éléments d'interface utilisateur qui se chevauchent en conséquence en conservant leur disposition pour iOS6. Pour ce faire, procédez comme suit:

    • Veiller à ce que Use Autolayout case n'est pas cochée pour votre Storyboard (c'est parce que sinon "iOS 6/7 Deltas" n'est pas affiché dans l'inspecteur de taille). Pour faire ça:
      • sélectionnez votre fichier Storyboard
      • afficher les utilitaires
      • sélectionnez "Afficher l'inspecteur de fichiers"
      • Sous "Document Builder Interface", décochez "Utiliser la mise en page automatique"
    • Facultativement, pour vous aider à surveiller les modifications de mise en page pour iOS 7 ET 6 lorsque vous les appliquez, sélectionnez «Assistant éditeur», sélectionnez «Aperçu» et «iOS 6.1 ou version antérieure»: entrez la description de l'image ici entrez la description de l'image ici
    • Sélectionnez maintenant l'élément d'interface utilisateur que vous souhaitez ajuster afin qu'il ne soit plus chevauché par la barre d'état
    • Sélectionnez "Afficher l'inspecteur de taille" dans la colonne Utilitaires
    • Repositionnez votre élément d'interface utilisateur le long de l'axe Y de la même hauteur que la hauteur de la barre d'état: entrez la description de l'image ici
    • Et modifiez la valeur des deltas iOS6 / 7 pour Y de la même quantité NÉGATIVE que la hauteur bg de la barre d'état (notez le changement dans l'aperçu iOS 6 si vous l'utilisez): entrez la description de l'image ici

ALTERNATIVES:

Pour ajouter encore moins de code dans les projets riches en storyboard et pour faire pivoter automatiquement l'arrière-plan de la barre d'état, au lieu d'ajouter par programme un arrière-plan pour votre barre d'état, vous pouvez ajouter une vue colorée à chaque contrôleur de vue qui se trouve tout en haut de la vue principale dudit contrôleur de vue. Vous changeriez alors le delta de hauteur de cette nouvelle vue en la même quantité négative que la hauteur de votre vue (pour la faire disparaître sous iOS 6).

L'inconvénient de cette alternative (bien que peut-être négligeable compte tenu de la compatibilité avec la rotation automatique) est le fait que cette vue supplémentaire n'est pas immédiatement visible si vous visualisez votre Storyboard pour iOS 6. Vous ne sauriez qu'elle est là si vous jetez un œil au " Document Outline "du Storyboard.

sts2055
la source
12

Si vous ne voulez pas que vos contrôleurs de vue soient chevauchés par la barre d'état (et les barres de navigation), décochez la case "Étendre les bords sous les barres supérieures" dans Interface Builder dans Xcode 5.

Décochez les bords étendus sous les barres supérieures

nvrtd frst
la source
7
Cela n'est possible que si vous utilisez un storyboard
Cœur
3
Il ne fonctionne qu'avec des conteneurs vcs tels que le contrôleur de navigation ou le contrôleur de tabulation
Andrea
2
bordsForExtendedLayout est uniquement utilisé par les contrôleurs de vue de conteneur (comme UINavigationController) pour déterminer si les vues des enfants doivent être chevauchées par le chrome du parent. La définition de cette propriété sur le contrôleur de vue racine pour UIWindow ne fait rien. Voir ma réponse ci-dessus: stackoverflow.com/questions/18294872/…
jaredsinclair
Comment faites-vous pour un UITabBarController @Andrea? Merci.
KarenAnne
@KarenAnne Dépendez si vous le faites par programme ou avec des storyboards. Par programme, il vous suffit de définir la propriété edgeForExtent sur ce que vous aimez dans le contrôleur de vue que vous affichez à l'intérieur de l'UITabBarViewController, mais pour ne pas avoir le problème de la barre d'état, vous devez charger un uinavigationcontroller à l'intérieur du UITabbarController. Vérifiez ici. developer.apple.com/library/ios/documentation/UserExperience/…
Andrea
11

Apple a publié Q & A technique QA1797: Empêcher la barre d'état de couvrir vos vues . Cela fonctionne bien pour les versions iOS 6 et iOS 7.

Igor
la source
5
Apple suppose que tout le monde utilise la mise en page automatique. La mise en page automatique était horrible dans Xcode 4, et Xcode 5 vient juste de sortir, c'est donc une hypothèse douteuse.
Glenn Maynard
1
Mais en perspective, c'est une meilleure solution que de redimensionner le cadre de la fenêtre racine ou la barre d'état.
Igor
Pour autant que je sache, la solution d'Apple ne fonctionne pas si votre rootViewController est un splitViewController.
Vern Jensen
8

J'ai vu de nombreux tutoriels pour résoudre ce problème. Mais aucun d'entre eux ne fonctionne! Voici ma solution, et cela fonctionne pour moi:

if( [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f ) {
    float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
    for( UIView *v in [self.view subviews] ) {
        CGRect rect = v.frame;
        rect.origin.y += statusBarHeight;
        v.frame = rect;
    }
}

La logique est simple. Je décale toutes les vues des enfants sur le self.view avec 20 pixels. C'est tout. Ensuite, la capture d'écran s'affichera comme sur iOS 6. Je déteste la barre d'état iOS7! ~ "~

firestoke
la source
2
où dois-je ajouter cela? dans l'application, le délégué a-t-il été lancé avec des options?
mhmdshawqi
Quand je fais cela, ma barre d'état devient blanche
ropo
6

Une petite alternative à la réponse d'Archy Holt, un peu plus simple:

une. Mettre UIViewControllerBasedStatusBarAppearanceà NOen info.plist

b. Dans AppDelegatel » application:didFinishLaunchingWithOptions:, composez le :

if ([[UIDevice currentDevice].systemVersion floatValue] < 7)
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
else
{
    // handling statusBar (iOS7)
    application.statusBarStyle = UIStatusBarStyleLightContent;
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    self.window.clipsToBounds = YES;

    // handling screen rotations for statusBar (iOS7)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

Et ajoutez la méthode:

- (void)applicationDidChangeStatusBarOrientationNotification:(NSNotification *)notification
{
    // handling statusBar (iOS7)
    self.window.frame = [UIScreen mainScreen].applicationFrame;
}

Vous pouvez également envisager de sous-classer UIWindowpour gérer UIApplicationDidChangeStatusBarOrientationNotificationlui-même.

Cœur
la source
avez-vous un problème avec presentViewController: animated: complétion:?
Tùng Đỗ
@ TùngĐỗ true, j'ai donc fait une alternative qui fonctionne mieux: stackoverflow.com/questions/18294872/…
Cœur
5

Je l'ai utilisé dans tous mes contrôleurs de vue, c'est simple. Ajoutez ces lignes dans toutes vos méthodes viewDidLoad:

- (void)viewDidLoad{
    //add this 2 lines:
    if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

    [super viewDidLoad];
}
IgniteCoders
la source
1
Fonctionné comme un charme, et mort facile. En mouvement rubis, avant l'appel à la super utilisation: self.edgesForExtendedLayout = UIRectEdgeNone if respondsToSelector ("edgeForExtendedLayout")
tehprofessor
4

Essayez cette méthode simple ....

Étape 1 : Pour changer en singleviewController

[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];

Étape 2 : Pour changer dans toute l'application

info.plist
      ----> Status Bar Style
                  --->UIStatusBarStyle to UIStatusBarStyleBlackOpaque

Étape 3 : ajoutez également ceci dans chacun viewWillAppearpour ajuster la statusbarhauteuriOS7

    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 7) {
        CGRect frame = [UIScreen mainScreen].bounds;
        frame.origin.y+=20.0;
        frame.size.height-= 20.0;
        self.view.frame = frame;
        [self.view layoutIfNeeded];
    }
Rajesh Loganathan
la source
3

J'ai atteint la barre d'état comme iOS 6 dans iOS 7.

Définissez UIViewControllerBasedStatusBarAppearance sur NO dans info.plist

Placez ce code dans la - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptionsméthode

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    [application setStatusBarStyle:UIStatusBarStyleLightContent];
    self.window.clipsToBounds =YES;
    self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height);

    //Added on 19th Sep 2013
    NSLog(@"%f",self.window.frame.size.height);
    self.window.bounds = CGRectMake(0,0, self.window.frame.size.width, self.window.frame.size.height);
}

Il peut pousser toutes vos vues de 20 pixels vers le haut. Pour venir, utilisez le code suivant dans la -(void)viewDidAppear:(BOOL)animatedméthode

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    CGRect frame=self.view.frame;
    if (frame.size.height==[[NSUserDefaults standardUserDefaults] floatForKey:@"windowHeight"])
    {
        frame.size.height-=20;
    }
    self.view.frame=frame;
}

Vous devez définir la valeur windowHeight Userdefaults après l'allocation de fenêtre dans la méthode didFinishLauncing comme

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[[NSUserDefaults standardUserDefaults] setFloat:self.window.frame.size.height forKey:@"windowHeight"];
Rose du désert
la source
Une meilleure approche consiste à rendre votre barre UINavigation heightégale à 64 au lieu de 44. Ensuite, votre barre s'étendra jusqu'au sommet comme dans les applications d'Apple.
Aaron Brager
@AaronBrager Mais mon exigence était de montrer la barre d'état de style iOS 6.
Desert Rose
Pouvez-vous s'il vous plaît ajouter la solution pour l'orientation paysage iOS 7?. Je fais la même chose. mais cela ne fonctionne pas dans iOS 7 Landscape.
sathiamoorthy
@DesertRose THX! Cela fonctionne pour moi, mais cela coupe la barre d'itabab en bas. J'ai une application basée sur un contrôleur de barre d'onglets avec 3 vues, dont 2 sont des contrôleurs de table.
marciokoko
1
JUSQU'À ce que je fasse pivoter l'appareil (mon appareil iOS 7 est un iPad), cela le corrige parfaitement. Mais une fois que je tourne, la barre noire reste exactement où elle est et la "vue" (désolé si ce n'est pas le bon terme technique, je suis un PhoneGap / web guy) conserve sa hauteur réduite - sauf que ce n'est plus la hauteur, c'est la largeur. Cette solution ne prend pas en charge la rotation, mais c'est la meilleure solution que j'ai vue - comment peut-elle être améliorée pour surveiller les rotations des appareils? Merci!
tylerl
2

Si vous utilisez le générateur d'interface, essayez ceci:

Dans votre fichier xib:

1) Sélectionnez la vue principale, définissez la couleur d'arrière-plan sur noir (ou sur la couleur souhaitée pour la barre d'état)

2) Assurez-vous que l'arrière-plan est une sous-vue autonome positionnée comme un enfant de niveau supérieur de la vue du contrôleur.
Déplacez votre arrière-plan pour devenir un enfant direct de la vue du contrôleur. Vérifiez le panneau de redimensionnement automatique pour vous assurer que vous avez verrouillé tous les bords du cadre, activé les deux axes de flexibilité et s'il s'agit d'un UIImageView, définissez le mode de contenu sur Echelle à remplir. Par programme, cela se traduit par contentMode défini sur UIViewContentModeScaleToFill et a son masque de redimensionnement automatique défini sur (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight).

3) Déplacez maintenant tout ce qui est verrouillé vers le haut - de 20 points vers le bas et définissez un delta Y iOS 6/7 sur -20.
Tous les enfants de niveau supérieur qui sont verrouillés sur le cadre supérieur dans le panneau de redimensionnement automatique doivent être abaissés de 20 pts et leur delta Y iOS 6/7 défini sur -20. (Cmd sélectionnez tous ceux-ci et cliquez 20 fois sur la flèche vers le bas - y a-t-il une meilleure façon pour quiconque?)

4) Ajustez la hauteur delta iOS 6/7 de tous les éléments ci-dessus qui avaient une hauteur flexible. Tous les éléments verrouillés en haut et en bas du cadre et dont la hauteur flexible était activée dans le panneau de redimensionnement automatique doivent également avoir leur hauteur delta iOS 6/7 réglée à 20. Cela inclut la vue d'arrière-plan mentionnée ci-dessus. Cela peut sembler anti-intuitif, mais en raison de l'ordre dans lequel ceux-ci sont appliqués, c'est nécessaire. La hauteur du cadre est définie en premier (en fonction de l'appareil), puis les deltas sont appliqués, et enfin les masques de redimensionnement automatique sont appliqués en fonction des positions de décalage de tous les cadres enfants - réfléchissez-y un peu, cela aura du sens.

5) Enfin, les éléments qui étaient verrouillés sur le cadre inférieur mais pas sur le cadre supérieur ne nécessitent aucun deltas.

Cela vous donnera la barre d'état identique dans iOS7 et iOS6.

D'un autre côté, si vous souhaitez un style iOS7 tout en conservant la compatibilité iOS6, définissez les valeurs delta Y / delta height sur 0 pour la vue d'arrière-plan.

Pour voir plus d'informations sur la migration iOS7, lisez l'article complet: http://uncompiled.blogspot.com/2013/09/legacy-compatible-offsets-in-ios7.html

thebman
la source
Aucun deltas lors de l'utilisation de la mise en page automatique
lostintranslation
2

Ma solution consistait à ajouter une UIViewhauteur de 20 points en haut de la fenêtre sur iOS 7. J'ai ensuite créé une méthode dans ma classe AppDelegate pour afficher / masquer l'arrière-plan de la barre d'état "solide". Dans application:didFinishLaunchingWithOptions::

// ...

// Add a status bar background
self.statusBarBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width, 20.0f)];
self.statusBarBackground.backgroundColor = [UIColor blackColor];
self.statusBarBackground.alpha = 0.0;
self.statusBarBackground.userInteractionEnabled = NO;
self.statusBarBackground.layer.zPosition = 999; // Position its layer over all other views
[self.window addSubview:self.statusBarBackground];

// ...
return YES;

Ensuite, j'ai créé une méthode pour faire apparaître / masquer l'arrière-plan de la barre d'état noire:

- (void) showSolidStatusBar:(BOOL) solidStatusBar
{
    [UIView animateWithDuration:0.3f animations:^{
        if(solidStatusBar)
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
            self.statusBarBackground.alpha = 1.0f;
        }
        else
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
            self.statusBarBackground.alpha = 0.0f;
        }
    }];
}

Tout ce que je dois faire maintenant, c'est appeler [appDelegate showSolidStatusBar:YES]quand c'est nécessaire.

Alexandre OS
la source
2

Cela peut être un problème majeur si vous utilisez la disposition automatique, car vous ne pouvez plus manipuler directement les cadres. Il existe une solution simple sans trop de travail.

J'ai fini par écrire une méthode utilitaire dans une classe utilitaire et je l'ai appelée à partir de la viewDidLayoutSubviewsméthode de tous les contrôleurs de vue .

+ (void)addStatusBarIfiOS7:(UIViewController *)vc
    {
        if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
            CGRect viewFrame = vc.view.frame;
            if(viewFrame.origin.y == 20) {
                //If the view's y origin is already 20 then don't move it down.
                return;
            }
            viewFrame.origin.y+=20.0;
            viewFrame.size.height-= 20.0;
            vc.view.frame = viewFrame;
            [vc.view layoutIfNeeded];
        }
    }

Remplacez votre viewDidLayoutSubviewsméthode dans le contrôleur de vue, où vous voulez la barre d'état. Il vous permettra de surmonter le fardeau de la mise en page automatique.

- (void)viewDidLayoutSubviews
{
    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    [super viewDidLayoutSubviews];
    [MyUtilityClass addStatusBarIfiOS7:self];
}
Selvin
la source
1

La façon la plus simple de le faire est d'installer un SDK plus ancien sur votre nouveau Xcode.

Comment installer un SDK plus ancien sur le dernier Xcode?

  1. Vous pouvez obtenir le SDK iOS 6.1 sur http://www.4shared.com/zip/NlPgsxz6/iPhoneOS61sdk.html ou télécharger un ancien Xcode et obtenir le SDK de son contenu

  2. Décompressez et collez ce dossier dans /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs

  3. Redémarrez le xcode.

  4. Vous pouvez désormais sélectionner un SDK plus ancien dans les paramètres de construction de votre projet

J'espère que cela vous aide. Cela a fonctionné pour moi =)

marcelosalloum
la source
travaillé pour moi. merci @marcelosalloum mais toujours à la recherche d'une solution de contournement pour mon application phonegap (uiwebview) pour prendre en charge la barre d'état transparente d'iOS7 pour une future mise à jour de mon application. Merci encore. ;)
hanisme
@marcellosaloum, êtes-vous sûr que l'application sera acceptée par Apple? Ils ont dit que les applications compilées avec XCode 4 ne seraient plus acceptées ... cela signifie en fait iOS 6 SDK.
Valerio
Mon application a en effet été acceptée car Xcode5 peut compiler des SDK iOS plus anciens. Je ne sais pas si AppStore rejettera les applications intégrées à Xcode4 mais (Xcode4! = IOS 6 SDK) comme vous l'avez dit.
marcelosalloum
C'était après le 1er février? Ce jour-là, Apple a rendu cela obligatoire.
Valerio
Non, j'ai touché ce code l'année dernière, folk. Je ne savais pas qu'Apple avait rendu cela obligatoire (pas content de le savoir cependant). Pourriez-vous s'il vous plaît poster ici le lien qui dit cela? Cheers
marcelosalloum
1

En utilisant presentViewController:animated:completion:foiré le window.rootViewController.view, j'ai dû trouver une approche différente à ce problème. Je l'ai finalement fait fonctionner avec des modaux et des rotations en sous-classant l'UIView de mon rootViewController.

.h

@interface RootView : UIView

@end

.m

@implementation RootView

-(void)setFrame:(CGRect)frame
{
    if (self.superview && self.superview != self.window)
    {
        frame = self.superview.bounds;
        frame.origin.y += 20.f;
        frame.size.height -= 20.f;
    }
    else
    {
        frame = [UIScreen mainScreen].applicationFrame;
    }

    [super setFrame:frame];
}

- (void)layoutSubviews
{
    self.frame = self.frame;

    [super layoutSubviews];
}

@end

Vous avez maintenant une solution de contournement solide pour les animations iOS7.

Cœur
la source
1

Je suis en retard pour cette réponse, mais je veux juste partager ce que j'ai fait, ce qui est fondamentalement la solution la plus simple

Tout d'abord-> Accédez à votre info.plistfichier et ajoutez un style de barre d'état-> Style noir transparent (alpha de 0,5)

Maintenant, ça y va: -

Ajoutez ce code dans votre AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
     //Whatever your code goes here
  if(kDeviceiPad){

     //adding status bar for IOS7 ipad
         if (IS_IOS7) {
              UIView *addStatusBar = [[UIView alloc] init];
              addStatusBar.frame = CGRectMake(0, 0, 1024, 20);
              addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //change this to match your navigation bar
              [self.window.rootViewController.view addSubview:addStatusBar];
                    }
                }
    else{

         //adding status bar for IOS7 iphone
        if (IS_IOS7) {
            UIView *addStatusBar = [[UIView alloc] init];
            addStatusBar.frame = CGRectMake(0, 0, 320, 20);
            addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //You can give your own color pattern
            [self.window.rootViewController.view addSubview:addStatusBar];
        }

    return YES;
   }
Vizllx
la source
0

Ma solution très simple (en supposant que seule l'orientation verticale est prise en charge) consiste à redéfinir les limites de la fenêtre d'application pour les versions iOS inférieures à 7, dans la méthode déléguée de l'application didFinishLaunchingWithOptions:

CGRect screenBounds = [[UIScreen mainScreen] bounds];
if ([HMService getIOSVersion] < 7) {
    // handling statusBar (iOS6) by leaving top 20px for statusbar.
    screenBounds.origin.y = 20;
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
else {
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
jki
la source
Votre code décale simplement le «y» de 0 à 20 mais n'ajuste pas la hauteur en conséquence, vous devez donc ajouter screenBounds.size.height - = 20; juste après screenBounds.origin.y = 20;
Amit
0

Vous pouvez masquer la barre d'état tous ensemble. Votre application sera donc en plein écran. Je pense que c'est le meilleur que vous obtiendrez.

UIStatusBarStyleNone ou défini dans les paramètres cibles.

Christopher Rex
la source
2
où spécifier UIStatusbarstylenone
user4951
0

Étapes pour masquer la barre d'état dans iOS 7:

1.Accédez au fichier info.plist de votre application.

2.Et définir, afficher l'apparence de la barre d'état basée sur le contrôleur: booléen NON

J'espère que j'ai résolu le problème de la barre d'état .....

chandrika
la source
0

Afin de continuer à travailler avec setStatusBarHidden: J'utilise cette catégorie:

@interface UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden;

@end

@implementation UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden{
    if (!IOS7) {
        [self setStatusBarHidden:statusBarHidden];
        return;
     }

    if ([self isStatusBarHidden] == statusBarHidden) {
        return;
    }

    [self setStatusBarHidden:statusBarHidden];
    [self keyWindow].clipsToBounds = YES;
    CGFloat offset = statusBarHidden ? 0 : 20;
    [self keyWindow].frame =  CGRectMake(0,offset,[self keyWindow].frame.size.width,[self keyWindow].frame.size.height-offset);
    [self keyWindow].bounds = CGRectMake(0, offset, [self keyWindow].frame.size.width,[self keyWindow].frame.size.height);
}

@end
Tomer Even
la source
0

Cela peut être trop tard pour être partagé, mais j'ai quelque chose à apporter qui pourrait aider quelqu'un, j'essayais de sous-classer l'UINavigationBar et je voulais le faire ressembler à ios 6 avec une barre d'état noire et un texte de barre d'état en blanc.

Voici ce que j'ai trouvé en travaillant pour ça

        self.navigationController?.navigationBar.clipsToBounds = true
        self.navigationController?.navigationBar.translucent = false
        self.navigationController?.navigationBar.barStyle = .Black
        self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()

Cela a rendu mon arrière-plan de barre d'état noir, le texte de la barre d'état blanc et la couleur de la barre de navigation blanche.

iOS 9.3, XCode 7.3.1

channi
la source