web-dev-qa-db-fra.com

iOS7 - Afficher sous la barre d'état - edgeForExtendedLayout ne fonctionne pas

J'ai un projet qui a été construit l'année dernière et qui utilise des XIB, pas de storyboards. Les XIB n'utilisent pas la mise en page automatique, mais ils utilisent certains dimensionnement automatique. J'ai un problème lors de l'exécution avec iOS7, dans lequel toutes les vues sont cachées sous la barre d'état. Je comprends tout à fait qu’il s’agisse d’une nouvelle fonctionnalité avec iOS7, dans laquelle on peut s’y attendre. Cependant, toutes les solutions pour le résoudre afin de ne pas le faire ne fonctionnent pas. J'ai une image en haut de la vue qui apparaît toujours sous la barre d'état, et je n'utilise pas de barre de navigation ni quoi que ce soit de ce genre.

J'ai essayé de mettre à jour les Y-deltas dans le XIB (ils n'ont aucun effet sur la vue), j'ai essayé de régler edgesForExtendedLayout sur UIRectEdgeNone (ne fait rien) et une multitude d'autres choses. Chaque fois, la barre d'état s'affiche avec la vue cachée sous celle-ci, peu importe ce que je fais .. c'est-à-dire, sauf si je déplace manuellement la vue dans XIB pour laisser de la place à la barre d'état (mais cette solution ne fonctionne pas, car ne semble pas correct dans iOS6, bien sûr).

Ce qui est étrange, c’est que même lorsque j’essaie de modifier une ligne de code avec une ligne de code, cela ne fonctionne pas (comme ce qui suit):

self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+20, self.view.frame.size.width, self.view.frame.size.height);

..Pas que j'irais avec ce genre de solution, mais c'est juste étrange que cela n'ait pas fonctionné (la seule fois où je vois généralement que cela ne fonctionne pas, c'est si la mise en page automatique est en place, ce qui n'est pas le cas dans ce cas).

C'est une exigence de conception que la barre d'état indique, et je ne comprends pas pourquoi je ne peux pas définir la vue pour qu'elle soit sous la barre d'état pour iOS7. J'ai lu chaque article de Stack Overflow sur le sujet, ainsi que les guides de transition/d'Apple. Encore une fois, pour réitérer, je comprends parfaitement comment cela devrait fonctionner et quelle devrait être la solution attendue, mais rien de tout cela ne semble fonctionner pour ce projet particulier. 

Je suis un développeur iOS expérimenté, mais ce projet a été créé par une autre équipe. Par conséquent, je ne sais pas s'il y a quelque chose de caché quelque part dans les fichiers XIB, le plist ou le code susceptible de dépasser les paramètres ci-dessus. S'il vous plaît laissez-moi savoir s'il y a autre chose qui peut être examiné à ce sujet, ou plus d'informations que je peux fournir.

Merci d'avance!

20
svguerin3

Si vous définissez les valeurs delta iOS 6/7 dans Interface Builder, n'oubliez pas de définir "View as" sur "iOS 6" dans le document Interface Builder, car il s'agit de la présentation iOS 6 que vous souhaitez répliquer. Les deltas ne seront alors utilisés que sur iOS 7 pour pousser le contenu sous la barre d'état. Si vous laissez l'option "Afficher en tant que" définie sur iOS 7 (valeur par défaut), les deltas vous donneront l'apparence iOS 7 sur iOS 6.

Toutefois, les deltas ne vous aideront pas si vous repositionnez ou redimensionnez des vues par programme en fonction du cadre de vue, car celui-ci ne prend pas en compte les deltas.

Au lieu d'utiliser les deltas, la meilleure solution que j'ai trouvée consiste à activer la présentation automatique sur votre XIB principal, puis à définir la contrainte d'espace supérieure sur votre vue supérieure/contenu pour qu'elle suive le Guide de présentation supérieure. Ce guide a été introduit dans iOS 7 et représente la position sous la barre d'état. Malheureusement, le guide n’est pas disponible dans Interface Builder lorsque vous n’utilisez pas de Storyboards, mais vous pouvez l’ajouter par programme.

Ce que j'ai fait, c'est ajouter une contrainte d'espace au sommet de la vue d'ensemble dans Interface Builder et créer un point de vente dans le code. Ensuite, dans viewDidLoad, si topLayoutGuide est disponible (iOS 7+), remplacez la contrainte de cette sortie par une version utilisant plutôt le Guide de mise en forme supérieur.

if ([self respondsToSelector:@selector(topLayoutGuide)]) {
    [self.view removeConstraint:self.containerTopSpaceConstraint];

    self.containerTopSpaceConstraint =
    [NSLayoutConstraint constraintWithItem:self.contentView
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:self.topLayoutGuide
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1
                                  constant:0];

    [self.view addConstraint:self.containerTopSpaceConstraint];

    [self.view setNeedsUpdateConstraints];
    [self.view layoutIfNeeded];
}
17
Kim André Sand

Pour référence, la solution ci-dessous a fonctionné lorsque je l'ai appliquée à mes ViewControllers. Cependant, ce n'est pas idéal et un peu hacky. Si c'est la seule approche que je peux adopter, alors qu'il en soit ainsi.

float systemVersion=[[[UIDevice currentDevice] systemVersion] floatValue];
if(systemVersion>=7.0f)
{
    CGRect tempRect;
    for(UIView *sub in [[self view] subviews])
    {
        tempRect = [sub frame];
        tempRect.Origin.y += 20.0f; //Height of status bar
        [sub setFrame:tempRect];
    }
}
6
svguerin3

Apple vous pousse à utiliser l'autolayout pour y parvenir. Vous devez définir une contrainte sur le "Guide de mise en page supérieur" à partir de la sous-vue supérieure de votre vue.

Voir ce document pour des exemples:

https://developer.Apple.com/library/ios/qa/qa1797/_index.html

Pour ce faire sans XIB, vous devez ajouter la contrainte par programmation. La documentation d'Apple en donne un bon exemple, que j'ai résumé ci-dessous.

Étant donné que topLayoutGuide est une propriété d'un contrôleur de vue, il vous suffit de l'utiliser dans votre dictionnaire de liaisons de variables. Ensuite, vous configurez votre contrainte comme d'habitude:

id topGuide = [myViewController topLayoutGuide];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(button, topGuide);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide]-20-[button]" options:0 metrics:nil views:viewsDictionary]; 

La documentation à ce sujet se trouve dans la référence de la classe UIViewController .

5
petehare

1) La solution la plus simple si vous n’avez pas l’esprit d’avoir une barre de navigation opaque:

self.navigationController.navigationBar.translucent = NO;

2) La réponse de svguerin3 ne peut pas fonctionner dans le cas général. Par exemple, si l'une de vos sous-vues utilise la taille automatique pour être accrochée au bas de son conteneur, sa nouvelle position sera fausse. Et dans le pire des cas, l'écran pourrait sortir de l'écran.

3
Aurelien Porte
- (void)viewDidAppear:(BOOL)animated {
        [self.view setFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height)];
// OR
        self.view.transform = CGAffineTransformMakeTranslation(0, 20);
}
2
Mazen Kasser

Si vous utilisez le storyboard, vous pouvez décocher la case "Sous barres opaques" dans l'inspecteur d'attributs

Storyboard

0
dhin

Avez-vous essayé d’afficher vos fichiers XIB en tant que source et de supprimer les lignes contenant des bords pour un affichage prolongé?

Nous avons dû supprimer cette ligne dans les scènes de notre scénario car les vues principales des scènes de notre scénario sont représentées par des XIB.

Ce qui se passait pour nous, c’est que dans certaines scènes, le contenu XIB de la vue principale de la scène était abaissé du fait de la hauteur de la barre d’état et de la barre de navigation.

La suppression de cette ligne permettait aux XIB d’être affichés comme si leur sommet s’apparentait au même sommet de la scène de son storyboard.

Malheureusement, nous ne savons pas du tout ce qui a déclenché cela, mais je l’ai vu se produire lors de la modification de l’ordre des contenus dans la vue principale de la XIB afin qu’une UITextView apparaisse en premier. La réorganisation de l'ordre des éléments après son déclenchement n'a eu aucun effet sur la suppression de ce comportement indésirable. 

J'espère que cela aidera tout le monde à rencontrer ce type de problème.

0
Alex Zavatone