254 votes

Explication de la différence entre automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout dans iOS7

J'ai lu beaucoup de choses sur la transition de l'interface utilisateur d'iOS7.

Je ne suis pas capable d'obtenir ce que ces trois propriétés automaticallyAdjustsScrollViewInsets , extendedLayoutIncludesOpaqueBars , edgesForExtendedLayout ? ?

Par exemple, j'essaie de faire en sorte que mes contrôleurs de vue commencent sous la barre d'état, mais je n'y parviens pas.

5 votes

Et pourquoi pensez-vous que je ne l'ai pas lu ? Le problème, c'est que ça ne fonctionne pas comme prévu, c'est-à-dire que je n'ai pas bien compris ! Voilà la raison.

1 votes

Ohhh j'ai mal compris ce que tu disais là. Je n'essayais pas d'être condescendant, c'est juste que lorsque certaines personnes posent des questions comme celle-ci, et qu'elles sont nouvelles sur le site, elles passent à côté de solutions évidentes.

8 votes

Dans votre méthode viewDidLoad, ajoutez if([self respondsToSelector:@selector(edgesForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone ; ce qui forcera votre vue à démarrer sous la barre d'état.

639voto

Antonio MG Points 16212

À partir d'iOS7, les contrôleurs de vue utilisent par défaut la disposition plein écran. En même temps, vous avez plus de contrôle sur la façon dont il dispose ses vues, et cela se fait avec ces propriétés :

edgesForExtendedLayout

En fait, cette propriété vous permet de définir les côtés de votre vue qui peuvent être étendus pour couvrir l'ensemble de l'écran. Imaginez que vous poussiez un UIViewController en un UINavigationController . Lorsque la vue de ce contrôleur de vue est mise en place, elle commence là où la barre de navigation se termine, mais cette propriété définit les côtés de la vue (haut, gauche, bas, droite) qui peuvent être étendus pour remplir tout l'écran.

Voyons cela à l'aide d'un exemple :

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];

Ici, vous ne définissez pas la valeur de edgesForExtendedLayout par conséquent, la valeur par défaut est prise ( UIRectEdgeAll ), la vue étend donc sa mise en page pour remplir tout l'écran.

Voici le résultat :

without edges for extended layout, the view fills the whole screen

Comme vous pouvez le voir, le fond rouge s'étend derrière la barre de navigation et la barre d'état.

Maintenant, vous allez régler cette valeur sur UIRectEdgeNone Vous dites donc au contrôleur de la vue de ne pas étendre la vue pour couvrir l'écran :

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
viewController.edgesForExtendedLayout = UIRectEdgeNone;
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];

Et le résultat :

with edgesForExtendedLayout set, the view is just under the navigation


automaticallyAdjustsScrollViewInsets

Cette propriété est utilisée lorsque votre vue est un UIScrollView ou similaire, comme un UITableView . Vous voulez que votre tableau commence là où la barre de navigation se termine, car sinon vous ne verrez pas tout le contenu, mais en même temps vous voulez que votre tableau couvre tout l'écran lors du défilement. Dans ce cas, le paramètre edgesForExtendedLayout à None ne fonctionnera pas car votre table commencera à défiler là où la barre de navigation se termine et ne passera pas derrière.

C'est ici que cette propriété est utile, si vous laissez le contrôleur de vue ajuster automatiquement les insertions (en donnant à cette propriété la valeur YES, qui est aussi la valeur par défaut), il ajoutera des insertions au sommet du tableau, de sorte que le tableau commencera là où la barre de navigation se termine, mais le défilement couvrira tout l'écran.

C'est quand il est réglé sur NON :

the table will scroll over the whole screen, but starts out partially covered

Et OUI (par défaut) :

the table scrolls over the whole screen, and starts just under the navigation

Dans les deux cas, le tableau défile derrière la barre de navigation, mais dans le deuxième cas (OUI), il commencera à partir du dessous de la barre de navigation.


extendedLayoutIncludesOpaqueBars

Cette valeur ne fait que s'ajouter aux précédentes. Par défaut, ce paramètre a pour valeur NO. Si la barre d'état est opaque, les vues ne seront pas étendues pour inclure la barre d'état, même si vous étendez votre vue pour la couvrir ( edgesForExtendedLayout a UIRectEdgeAll ).

Si vous donnez la valeur YES, cela permettra à la vue de repasser sous la barre d'état.

Si quelque chose n'est pas clair, écrivez un commentaire et je vous répondrai.

Comment iOS sait-il quel UIScrollView utiliser ?

iOS saisit la première sous-vue dans la vue de votre ViewController, celle qui se trouve à l'indice 0, et si c'est une sous-classe de UIScrollView puis lui applique les propriétés expliquées.

Bien sûr, cela signifie que UITableViewController fonctionne par défaut (puisque l UITableView est la première vue).

0 votes

Nous devons définir ces propriétés uniquement si nous affichons la barre de navigation par défaut, et non pas si la barre de navigation est personnalisée, n'est-ce pas ?

1 votes

Non, si vous utilisez la barre de navigation iOS mais avec votre propre design, vous devrez utiliser les mêmes propriétés. Si vous créez votre barre de navigation de toutes pièces, ces propriétés ne fonctionneront pas.

0 votes

Je ne comprends pas pourquoi il y a une petite couche noirâtre sur toute la vue ? Aidez-moi, s'il vous plaît. :/

15voto

Ali Beadle Points 346

Je ne sais pas si vous utilisez des storyboards, mais si c'est le cas, faites en sorte que vos contrôleurs de vue commencent sous la barre d'état (et au-dessus de la barre inférieure) :

Sélectionnez le contrôleur de vue dans IB, Dans l'inspecteur des attributs, désélectionnez les options "Extension des bords - sous les barres supérieures" et "Extension des bords - sous les barres inférieures".

0 votes

OK. Ensuite, je pense que ce que Nandha a suggéré ci-dessus permettra d'obtenir le même résultat de manière programmatique. Si cela ne fonctionne pas sous viewDidLoad, il faudra peut-être le déplacer vers viewDidLayoutSubviews.

0 votes

Indique si la disposition étendue inclut ou non des barres opaques. @property(nonatomic, assign) BOOL extendedLayoutIncludesOpaqueBars Discussion La valeur par défaut est NO.

0 votes

+1, Vous m'avez donné un indice pour vérifier dans Storyboard. Et j'ai résolu la moitié de mon problème.

11voto

J'utilise des storyboards et les conseils ci-dessus ont fonctionné, mais je ne savais pas exactement comment les mettre en œuvre. Vous trouverez ci-dessous un court exemple en swift de la manière dont le problème a été résolu en plaçant la solution recommandée dans le ViewController.

import Foundation
import UIKit

// This ViewController is connected to a view on a storyboard that 
// has a scrolling sub view.
class TheViewController: UIViewController {

  // Prepares the view prior to loading.  Putting it in viewDidAppear didn't work.
  override func viewWillAppear(animated: Bool) {

    // this method is an extension of the UIViewController 
    // so using self works as you might expect.
    self.automaticallyAdjustsScrollViewInsets = false

    // Default is "true" so this sets it to false tells it to use 
    // the storyboard as you have it placed
    // and not how it thinks it should place it.
  }

}

Mon problème : L'ajustement automatique est réglé sur vrai par défaut, ce qui entraîne une différence entre la conception du storyboard et le simulateur. Auto Adjust set to true by default causing a difference between storyboard design and simulator

Résolu : Le code ci-dessus a été appliqué, désactivant l'auto-ajustement. Code above applied, turning off the auto-adjust.

5voto

user3430340 Points 51

J'ai résolu ce problème en ajoutant cette ligne, mais mon problème était lié à une UIView pas UIScrollView

self.navigationController.navigationBar.translucent = NO;

2voto

Vojta Rujbr Points 170

N'oubliez pas que automaticallyAdjustsScrollViewInsets ne fonctionne que si un type de vue de défilement (vue de table, vue de collection,...) est soit

  • La vue de VC, ou
  • Première sous-vue de cette vue

D'autres ont suggéré que cela ne fonctionne pas même si c'est la première vue secondaire, mais qu'il y a d'autres vues défilantes dans la hiérarchie des vues.

EDIT (extension DIY)

Si vous souhaitez un comportement similaire même si vous ne pouvez pas remplir ces conditions (par exemple, si vous avez une image de fond sous la vue défilante), vous pouvez ajuster manuellement les inserts de la vue défilante. Mais s'il vous plaît, ne le réglez pas sur une valeur constante comme 44 ou 64 ou même 20 comme beaucoup le suggèrent dans SO. Vous ne pouvez pas connaître la taille à tout moment. Il peut y avoir la notification d'appel/gps/audio, la barre de navigation n'a pas besoin d'être toujours à 44 pts, etc.

Je pense que la meilleure solution est d'utiliser layoutGuide length dans didLayoutSubviews :

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: 0, right: 0)
    scrollView.scrollIndicatorInsets = scrollView.contentInset
}

Vous pouvez utiliser le bottomLayoutGuide de la même manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X