web-dev-qa-db-fra.com

Expliquer la différence entre automatiquementAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgeForExtendedLayout dans iOS7

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

Je ne peux pas 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 démarrent en dessous de la barre d'état, mais je ne parviens pas à l'obtenir.

243
user1010819

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

edgeForExtendedLayout

En gros, avec cette propriété, vous définissez quels côtés de votre vue peuvent être étendus pour couvrir tout l'écran. Imaginez que vous poussez un UIViewController dans un UINavigationController. Lorsque la vue de ce contrôleur de vue est affichée, elle commence à l'endroit où se termine la barre de navigation, mais cette propriété définit les côtés de la vue (haut, gauche, bas, droite) pouvant être étendus pour remplir tout l'écran.

Voyons le avec 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), de sorte que la vue étend sa disposition pour remplir tout l'écran.

Voici le résultat:

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

Comme vous pouvez le constater, l'arrière-plan rouge s'étend derrière la barre de navigation et la barre d'état.

Maintenant, vous allez définir cette valeur sur UIRectEdgeNone, de sorte que vous indiquez au contrôleur de 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


automatiquementAdjustsScrollViewInsets

Cette propriété est utilisée lorsque votre vue est une UIScrollView ou similaire, comme une UITableView. Vous voulez que votre tableau commence à l'endroit où se termine la barre de navigation, car vous ne verrez pas tout le contenu sinon, mais vous voulez aussi que votre tableau couvre tout l'écran lors du défilement. Dans ce cas, la définition de edgesForExtendedLayout sur Aucune ne fonctionnera pas, car votre tableau commencera à faire défiler l'emplacement de la barre de navigation à la fin et ne suivra pas.

C’est ici que cette propriété est utile, si vous laissez le contrôleur de vue ajuster automatiquement les incrustations (définissez cette propriété sur OUI, ainsi que sur la valeur par défaut), des incrustations seront ajoutées au haut de la table. la barre se termine, mais le défilement couvrira tout l'écran.

C'est quand est réglé sur NO:

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 second cas (OUI), il commencera par le dessous de la barre de navigation.


extendedLayoutIncludesOpaqueBars

Cette valeur est juste un ajout aux précédents. Par défaut, ce paramètre est défini sur 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 à UIRectEdgeAll).

Si vous définissez la valeur sur YES, la vue sera à nouveau visible sous la barre d'état.

Si quelque chose n'est pas clair, écrivez un commentaire et je vais y répondre.

Comment iOS sait-il ce que UIScrollView doit utiliser?

iOS saisit la première sous-vue de la vue de votre ViewController, celle de l'index 0, et s'il s'agit d'une sous-classe de UIScrollView, elle lui applique les propriétés expliquées.

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

605
Antonio MG

Vous ne savez pas si vous utilisez des storyboards, mais si c'est le cas, pour que vos contrôleurs de vue démarrent en dessous de la barre d'état (et au-dessus de la barre du bas):

Sélectionnez le contrôleur de vue dans IB. Dans l'inspecteur d'attributs, désélectionnez "Étendre les bords - Barres inférieures" et "Étendre les bords - Barres inférieures".

15
Ali Beadle

J'utilise des storyboards et les conseils ci-dessus ont fonctionné, mais je ne savais pas exactement comment le mettre en œuvre. Vous trouverez ci-dessous un bref exemple dans Swift montrant comment le problème a été résolu en mettant la solution recommandée dans 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: le réglage automatique est défini sur true par défaut, ce qui crée 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: Code ci-dessus appliqué, désactivant le réglage automatique. Code above applied, turning off the auto-adjust.

10

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

self.navigationController.navigationBar.translucent = NO;
5
user3430340

N'oubliez pas que la propriété automaticallyAdjustsScrollViewInsets ne fonctionne que si une 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 fonctionne, même s'il s'agit de la première sous-vue, mais il existe d'autres vues de défilement dans la hiérarchie des vues.

EDIT (extension bricolage)

Si vous souhaitez un comportement similaire même si vous ne pouvez pas remplir ces conditions (par exemple, vous avez une image d'arrière-plan sous la vue de défilement), vous pouvez régler les encarts de la vue de défilement manuellement. Mais s'il vous plaît, ne réglez pas cette valeur comme 44 ou 64 ou même 20, comme beaucoup le suggèrent autour de SO. Vous ne pouvez pas connaître la taille jamais. Il peut y avoir la notification d'incall/gps/audio, la barre de navigation ne doit pas toujours être 44 pts etc.

Je pense que la meilleure solution consiste à 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 bottomLayoutGuide de la même manière.

2
Vojta Rujbr