web-dev-qa-db-fra.com

La barre d'état et la barre de navigation apparaissent au-dessus des limites de ma vue dans iOS 7

J'ai récemment téléchargé Xcode 5 DP pour tester mes applications sous iOS 7. La première chose que j'ai remarquée et confirmée est que les limites de ma vue ne sont pas toujours redimensionnées pour prendre en compte la barre d'état et la barre de navigation.

Dans viewDidLayoutSubviews, j'imprime les limites de la vue:

{{0, 0}, {320, 568}}

En conséquence, mon contenu apparaît sous la barre de navigation et la barre d'état.

Je sais que je pourrais tenir compte de la hauteur moi-même en obtenant la hauteur de l'écran principal, en soustrayant la hauteur de la barre d'état et celle de la barre de navigation, mais cela semble être un travail supplémentaire inutile.

Comment puis-je résoudre ce problème?

Mise à jour:

J'ai trouvé une solution à ce problème spécifique. Définissez la propriété translucide de la barre de navigation sur NO:

self.navigationController.navigationBar.translucent = NO;

Cela empêchera la vue d'être encadrée sous la barre de navigation et la barre d'état.

Cependant, je n'ai pas trouvé de solution pour le cas où vous souhaitez que la barre de navigation soit translucide. Par exemple, lorsque vous visualisez une photo en plein écran, je souhaite que la barre de navigation soit translucide et que la vue soit encadrée en dessous. Cela fonctionne, mais lorsque je bascule l'affichage/le masquage de la barre de navigation, j'ai constaté des résultats encore plus étranges. La première sous-vue (UIScrollView) obtient ses limites et son origine est modifiée à chaque fois.

432
beebcon

Vous pouvez y parvenir en implémentant une nouvelle propriété appelée edgesForExtendedLayout dans iOS7 SDK. S'il vous plaît ajouter le code suivant pour y parvenir,

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

Vous devez ajouter ce qui précède dans votre méthode -(void)viewDidLoad.

iOS 7 apporte plusieurs modifications à la mise en page et à la personnalisation de l'apparence de votre UI. Les modifications apportées à la disposition du contrôleur de vue, à la couleur de teinte et à la police ont une incidence sur tous les objets UIKit de votre application. En outre, les améliorations apportées aux API de reconnaissance des gestes vous permettent de contrôler plus finement les interactions entre les gestes.

Utilisation des contrôleurs de vue

Dans iOS 7, les contrôleurs de vue utilisent la disposition en plein écran. Dans le même temps, iOS 7 vous offre un contrôle plus granulaire sur la manière dont un contrôleur de vue affiche ses vues. En particulier, le concept de disposition en plein écran a été affiné pour permettre à un contrôleur de vue de spécifier la disposition de chaque bord de sa vue.

La propriété du contrôleur de vue wantsFullScreenLayout est obsolète dans iOS 7. Si vous spécifiez actuellement wantsFullScreenLayout = NO, le contrôleur de vue peut afficher son contenu à un emplacement d'écran inattendu lorsqu'il s'exécute dans iOS 7.

Pour ajuster la manière dont un contrôleur de vue affiche ses vues, UIViewController fournit les propriétés suivantes:

  • edgeForExtendedLayout

La propriété edgesForExtendedLayout utilise le type UIRectEdge, qui spécifie chacun des quatre bords d’un rectangle, en plus de spécifier aucun et tout. Utilisez edgesForExtendedLayout pour spécifier les bords d'une vue à étendre, quelle que soit la transparence de la barre. Par défaut, la valeur de cette propriété est UIRectEdgeAll.

  • extendedLayoutIncludesOpaqueBars

Si votre conception utilise des barres opaques, raffinez edgesForExtendedLayout en définissant également la propriété extendedLayoutIncludesOpaqueBars sur NO. (La valeur par défaut de extendedLayoutIncludesOpaqueBars est NO.)

  • automatiquementAdjustsScrollViewInsets

Si vous ne souhaitez pas que les éléments de contenu de la vue de défilement soient ajustés automatiquement, définissez automaticallyAdjustsScrollViewInsets sur NO. (La valeur par défaut de automaticallyAdjustsScrollViewInsets est YES.)

  • topLayoutGuide, bottomLayoutGuide

Les propriétés topLayoutGuide et bottomLayoutGuide indiquent l'emplacement des bords supérieur et inférieur de la barre dans la vue d'un contrôleur de vue. Si les barres doivent chevaucher le haut ou le bas d'une vue, vous pouvez utiliser Interface Builder pour positionner la vue par rapport à la barre en créant des contraintes au bas de topLayoutGuide ou au haut de bottomLayoutGuide. (Si aucune barre ne doit chevaucher la vue, le bas de topLayoutGuide est le même que le haut de la vue et le haut de bottomLayoutGuide est le même que le bas de la vue.) Les deux propriétés sont créées paresseusement à la demande.

Veuillez vous référer, doc Apple

494
Nandha

Vous n'avez pas à calculer jusqu'où tout décaler, il y a une propriété intégrée pour cela. Dans Interface Builder, mettez en surbrillance votre contrôleur de vue, puis accédez à l'inspecteur d'attributs. Ici, vous verrez des cases à cocher à côté des mots "Étendre les bords". Comme vous pouvez le constater, dans la première capture d'écran, la sélection par défaut est que le contenu apparaisse sous les barres supérieure et inférieure, mais pas sous les barres opaques. C'est pourquoi il a été intéressant de définir le style de barre sur non translucide.

Comme vous pouvez le constater dans la première capture d'écran, deux éléments de l'interface utilisateur se cachent sous la barre de navigation. (J'ai activé les structures filaires dans IB pour illustrer cela) Ces éléments, un UIButton et un UISegmentedControl, ont tous deux leur origine "y" définie sur zéro et le contrôleur de vue est défini pour autoriser le contenu situé sous la barre supérieure.

enter image description here

Cette seconde capture d'écran montre ce qui se passe lorsque vous décochez la case "Under Top Bars". Comme vous pouvez le constater, la vue Contrôleurs de vue a été déplacée vers le bas pour que son origine soit directement sous la barre de navigation.

enter image description here

Cela peut également être accompli par programme grâce à l'utilisation de -[UIViewController edgesForExtendedLayout]. Voici un lien vers la référence de classe pour edgeForExtendedLayout , et pour IRectEdge

[self setEdgesForExtendedLayout:UIRectEdgeNone];
110
Mick MacCallum

J'ai créé ma vue par programme et cela a fini par fonctionner pour moi:

- (void) viewDidLayoutSubviews {
    // only works for iOS 7+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;

        // snaps the view under the status bar (iOS 6 style)
        viewBounds.Origin.y = topBarOffset * -1;

        // shrink the bounds of your view to compensate for the offset
        viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
        self.view.bounds = viewBounds;
    }
}

Source (dans la section topLayoutGuide au bas de la page 39).

33
Stunner

Solution Swift 3/Swift 4 qui fonctionne également avec les fichiers NIB/XIB sous iOS 10+:

override func viewDidLoad() {
    super.viewDidLoad()

    edgesForExtendedLayout = []
}
26
flo_23

Si vous voulez que la vue ait la barre de navigation translucide (ce qui est assez sympa), vous devez configurer un contentInset ou similaire.

Voici comment je le fais:

// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) {
      CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
      float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;

      myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);
}
10
Magnus

Dans votre fichier de liste d'applications, ajoutez une ligne, appelez-la "Afficher l'apparence de la barre d'état basée sur le contrôleur" et définissez-la sur NO.

9
Idan

edgesForExtendedLayout fait l'affaire pour iOS 7. Toutefois, si vous construisez l'application via iOS 7 SDK et le déployez dans iOS 6, la barre de navigation apparaît en translucide et les vues sous celle-ci. Donc, pour le réparer à la fois pour iOS 7 et pour iOS 6, procédez comme suit:

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific
9
Raj Pawan Gumdal

L'astuce la plus simple consiste à ouvrir le fichier NIB et à effectuer ces deux étapes simples:

  1. Basculez-le et réglez-le sur celui que vous préférez:

Enter image description here

  1. Sélectionnez ces/UIView/UIIMageView/... que vous voulez déplacer. Dans mon cas, seul le logo était superposé et j’ai réglé le delta sur +15; (OU -15 si vous avez choisi iOS 7 à l'étape 1)

Enter image description here

Et le résultat :

BeforeAfter

7
Riskov

Solution rapide:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None
}
5
fatihyildizhan

Swift

override func viewWillAppear(_ animated: Bool) {
    self.edgesForExtendedLayout = []
}
4
Shahrukh

J'aimerais développer la réponse de Stunner et ajouter une instruction if pour vérifier s'il s'agit d'iOS-7, car lorsque je l'aurais testée sur iOS 6, mon application se bloquerait.

L'addition serait d'ajouter:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

Je suggère donc d'ajouter cette méthode à votre fichier MyViewControler.m:

- (void) viewDidLayoutSubviews {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;
        viewBounds.Origin.y = topBarOffset * -1;
        self.view.bounds = viewBounds;
    }
}
4
werdsackjon

J'ai un scénario dans lequel j'utilise le BannerViewController écrit par Apple pour afficher mes annonces et un ScrollViewController intégré au BannerViewController.

Pour empêcher la barre de navigation de masquer mon contenu, je devais apporter deux modifications.

1) Modifier BannerViewController.m

- (void)viewDidLoad
{
   [super viewDidLoad];
   float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
   if (systemVersion >= 7.0) {
      self.edgesForExtendedLayout = UIRectEdgeNone;
   }
}

2) Modifier mon ScrollViewContoller

- (void)viewDidLoad
{
    [super viewDidLoad];
    float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (systemVersion >= 7.0) {
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

Désormais, les annonces s'affichent correctement en bas de la vue au lieu d'être couvertes par la barre de navigation et le contenu en haut n'est pas coupé.

3
Xavier John

faire une contrainte à Top Layout comme ceci enter image description here

2
carmen_munich

il suffit de définir le code suivant dans la vue apparaîtra.

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
 }
2
Amit Shelgaonkar

Pour moi, la solution la plus simple consiste à ajouter deux clés dans le plist

enter image description here

1
giuseppe

Swift 4.2 - Xcode 10.0 - iOS 12.0:

if #available(iOS 11.0, *) {} else {
  self.edgesForExtendedLayout = []
  self.navigationController?.view.backgroundColor = .white
}
1
juliancadi

Ajoutez la clé "Afficher l'apparence de la barre d'état basée sur le contrôleur" dans la liste déroulante sous la forme d'une ligne dans info.plist. Quelque chose comme ça:

Enter image description here

1
Kursat Turkay

J'ai eu le même problème avec mon application sur iPads (armv7, armv7s, amr64) uniquement en présentant un autre contrôleur UIViewController et après les avoir licenciés, la barre de navigation s'affiche sous la barre d'état ... Je passe beaucoup de temps à trouver une solution à ce problème. J'utilise le storyboard et dans InterfaceBuilder pour UIViewController, ce qui est horrible. J'ai paramétré Presentation from FullScreen -> Contexte actuel pour résoudre ce problème. Cela fonctionne dans mon application uniquement pour les iPad => iOS8.0 (tester avec iOS8.1) et pour les iPad avec iOS 7.1 ne fonctionne pas! see screenshot

1
Alexej W.

Steps For Masquer la barre d'état dans iOS 7:

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

2.And Set, Afficher l’apparence de la barre d’état basée sur le contrôleur: Boolean NO

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

0
chandrika

Dans mon cas, avec loadView () interrompu
ce code: self.edgesForExtendedLayout = UIRectEdgeNone

mais après avoir supprimé loadView (), tout a bien fonctionné

0
DevB2F