Expliquer la différence entre automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout dans iOS7

j'ai beaucoup lu sur la transition iOS7 UI.

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

par exemple, j'essaie de faire démarrer mes contrôleurs de vue en dessous de la barre d'état, mais je ne suis pas en mesure de l'atteindre.

227
demandé sur KlimczakM 2013-09-14 09:52:47

5 réponses

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

edgesForExtendedLayout

en gros, avec cette propriété vous définissez quels côtés de votre vue peuvent être étendus pour couvrir l'écran entier. Imaginez que vous poussiez un UIViewController dans un UINavigationController . Quand la vue de ce le contrôleur de vue est disposé, il commencera là où la barre de navigation se termine, mais cette propriété définira quels côtés de la vue (haut, gauche, bas, droite) peuvent être étendus pour remplir l'écran entier.

voyons cela 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 , donc la valeur par défaut est prise ( UIRectEdgeAll ), donc la vue étend sa disposition pour remplir l'écran entier.

C'est 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 définir cette valeur à UIRectEdgeNone , si vous dites la-vue-contrôleur de ne pas étendre la vue de 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 une UIScrollView ou similaire, comme un UITableView . Vous voulez que votre table commence là où la barre de navigation se termine, parce que vous ne verrez pas le contenu entier si ce n'est pas le cas, mais en même temps vous voulez que votre table couvre tout l'écran lors du défilement. Dans ce cas, paramétrer edgesForExtendedLayout à None ne fonctionnera pas car votre table commencera à défiler où le la barre de navigation se termine et ne va pas derrière.

voici où cette propriété est utile, si vous laissez le contrôleur de vue ajuster automatiquement les insets (en définissant cette propriété à Oui, aussi la valeur par défaut) il va ajouter insets au haut de la table, de sorte que la table commencera là où la barre de navigation se termine, mais le rouleau couvrira l'écran entier.

c'est quand est réglé à 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, la table défile derrière la barre de navigation, mais dans le second cas (oui), elle commencera par dessous la barre de navigation.

extendedLayoutIncludesOpaqueBars

cette valeur n'est qu'un ajout aux précédentes. Par défaut, ce paramètre est défini sur AUCUN. Si l' 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 à Oui, cela permettra à la vue de passer sous la barre d'État à nouveau.

si quelque chose n'est pas clair, écrivez un commentaire et j'y répondrai.

comment iOS sait-il ce Qu'UIScrollView doit utiliser?

iOS saisit le premier subview dans la vue de votre ViewController, celui de l'index 0, et si c'est une sous-classe de UIScrollView , alors il applique les propriétés expliquées.

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

579
répondu Antonio MG 2017-03-16 14:51:04

pas sûr si vous utilisez des storyboards, mais si vous l'êtes, pour faire démarrer vos contrôleurs de vue sous la barre d'état (et au-dessus de la barre du bas):

sélectionnez le contrôleur de vue en IB, Dans l'attribut inspector, désélectionnez "Extend Edges-Under Top Bars" et "Extend Edges - Under Bottom Bars".

15
répondu Ali Beadle 2013-10-07 06:32:58

j'utilise des storyboards et les conseils ci-dessus ont fonctionné mais je ne savais pas exactement comment les mettre en œuvre. Voici un bref exemple dans swift de la façon dont il a résolu le problème en mettant 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: Ajustement automatique de true par défaut, ce qui fait une différence entre la conception du scénario-maquette et celle du simulateur Auto Adjust set to true by default causing a difference between storyboard design and simulator

résolu: Code ci-dessus appliqué, désactivation l'auto-ajustement. Code above applied, turning off the auto-adjust.

10
répondu Christopher Wade Cantley 2014-11-18 16:30:47

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;
5
répondu user3430340 2017-09-04 12:21:23

Juste garder à l'esprit qu' automaticallyAdjustsScrollViewInsets la propriété ne fonctionne que si une sorte de défilement (vue de la table, vue de la collection,...) est soit

  • Le point de vue de la VC, ou
  • Premier sous-vue de ce point de vue

" D'autres ont suggéré que cela fonctionne même si c'est la première sous-vue, mais il y a d'autres vues de défilement dans la hiérarchie de la vue.

MODIFIER (extension de BRICOLAGE)

si vous voulez un comportement similaire même si vous ne pouvez pas remplir ces conditions (par exemple, vous avez une image de fond au-dessous de la vue scroll), vous pouvez ajuster les insets de la vue scroll manuellement. Mais s'il vous plaît ne mettez pas à constante comme 44 ou 64 ou même 20 comme beaucoup le suggèrent autour de SO. Tu ne peux pas connaître la taille. Il peut y avoir la notification incall/gps/audio, la barre de navigation n'a pas à être toujours 44 pts etc.

je pense que la meilleure solution est d'utiliser layoutGuide length 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.

2
répondu Vojta Rujbr 2017-05-15 09:29:52