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.
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 actuellementwantsFullScreenLayout = 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 typeUIRectEdge
, qui spécifie chacun des quatre bords d’un rectangle, en plus de spécifier aucun et tout. UtilisezedgesForExtendedLayout
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é estUIRectEdgeAll
.
- 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 deextendedLayoutIncludesOpaqueBars
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 deautomaticallyAdjustsScrollViewInsets
est YES.)
- topLayoutGuide, bottomLayoutGuide
Les propriétés
topLayoutGuide
etbottomLayoutGuide
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 detopLayoutGuide
ou au haut de bottomLayoutGuide. (Si aucune barre ne doit chevaucher la vue, le bas detopLayoutGuide
est le même que le haut de la vue et le haut debottomLayoutGuide
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
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.
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.
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];
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).
Solution Swift 3/Swift 4 qui fonctionne également avec les fichiers NIB/XIB sous iOS 10+:
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = []
}
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);
}
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.
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
L'astuce la plus simple consiste à ouvrir le fichier NIB et à effectuer ces deux étapes simples:
Et le résultat :
Solution rapide:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.edgesForExtendedLayout = UIRectEdge.None
}
Swift
override func viewWillAppear(_ animated: Bool) {
self.edgesForExtendedLayout = []
}
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;
}
}
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é.
il suffit de définir le code suivant dans la vue apparaîtra.
if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
Pour moi, la solution la plus simple consiste à ajouter deux clés dans le plist
Swift 4.2 - Xcode 10.0 - iOS 12.0:
if #available(iOS 11.0, *) {} else {
self.edgesForExtendedLayout = []
self.navigationController?.view.backgroundColor = .white
}
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:
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!
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 .....
Dans mon cas, avec loadView () interrompu
ce code: self.edgesForExtendedLayout = UIRectEdgeNone
mais après avoir supprimé loadView (), tout a bien fonctionné