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

250

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

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 sous la barre d'état, mais je ne suis pas en mesure d'y parvenir.

user1010819
la source
5
et pourquoi pensez-vous que je n'ai pas lu cela? .. Le problème est que cela ne fonctionne pas comme prévu car je ne l'ai pas bien compris !! .. c'est la raison
user1010819
1
Ohhh, j'ai mal compris ce que tu disais là-bas. Je n'essayais pas de paraître condescendant, c'est juste que lorsque certaines personnes posent des questions comme celle-ci et sont nouvelles sur le site, elles manquent les solutions évidentes.
erdekhayser du
8
Dans votre méthode viewDidLoad, ajoutez if ([self respondsToSelector: @selector (bordsForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; ce qui forcera votre vue à démarrer sous la barre d'état.
Nandha

Réponses:

629

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

bordsForExtendedLayout

Fondamentalement, avec cette propriété, vous définissez les côtés de votre vue qui peuvent être étendus pour couvrir tout l'écran. Imaginez que vous poussiez un UIViewControllerdans un UINavigationController. Lorsque la vue de ce contrôleur de vue est disposée, elle commencera là où se termine la barre de navigation, mais cette propriété définira les côtés de la vue (haut, gauche, bas, droite) qui peuvent être étendus pour remplir tout l'écran.

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, 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:

sans bords pour une disposition étendue, la vue remplit tout l'écran

Comme vous pouvez le voir, 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, vous dites donc 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:

avec edgeForExtendedLayout défini, la vue est juste sous la navigation


ajuste automatiquementScrollViewInsets

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

Voici où cette propriété est utile, si vous laissez le contrôleur de vue ajuster automatiquement les encarts (en définissant cette propriété sur YES, également la valeur par défaut), il ajoutera des encarts en haut du tableau, de sorte que le tableau commencera là où la navigation se termine, mais le défilement couvrira tout l'écran.

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

le tableau défile sur tout l'écran, mais commence partiellement couvert

Et OUI (par défaut):

le tableau défile sur tout l'écran et démarre juste sous la 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 n'est qu'un ajout aux précédentes. 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 OUI, cela permettra à la vue de passer à nouveau sous la barre d'état.

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

Comment iOS sait-il quel UIScrollView utiliser?

iOS récupère 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, UIScrollViewlui applique les propriétés expliquées.

Bien sûr, cela signifie que cela UITableViewControllerfonctionne par défaut (puisque UITableViewc'est la première vue).

Antonio MG
la source
Nous devons définir ces propriétés uniquement si, nous affichons la barre de navigation par défaut, et non si sa barre de navigation personnalisée, non?
Hemang
1
Non, si vous utilisez la barre de navigation iOS mais avec votre propre conception, vous devrez utiliser les mêmes propriétés. Si vous créez simplement votre barre de navigation par zéro, ces propriétés ne fonctionneront pas.
Antonio MG
Je ne comprends pas pourquoi il y a une petite couche noirâtre sur toute la vue? Veuillez aider? : /
aZtraL-EnForceR
24
Cette explication est bien meilleure que le Guide de transition de l'interface utilisateur iOS 7. Cela devrait simplement remplacer le guide, ce qui n'avait aucun sens pour moi.
Sam
2
Je pense que extendedLayoutIncludesOpaqueBars devrait être OUI par défaut au lieu de NON. La modification des couleurs d'affichage (translucidité) ne doit pas affecter la mise en page.
Vladimír Slavík
15

Je ne sais pas si vous utilisez des storyboards, mais si vous l'êtes, pour 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 d'attributs, désélectionnez «Étendre les bords - sous les barres supérieures» et «Étendre les bords - sous les barres inférieures».

Ali Beadle
la source
D'ACCORD. Ensuite, je pense que ce que Nandha a suggéré ci-dessus permettra d'atteindre le même résultat par programme. S'il ne fonctionne pas sous viewDidLoad, il peut être nécessaire de le déplacer vers viewDidLayoutSubviews.
Ali Beadle
Indique si la disposition étendue comprend ou non des barres opaques. @property (nonatomic, assign) BOOL extendedLayoutIncludesOpaqueBars Discussion La valeur par défaut est NO.
Abdul Yasin
+1, vous m'avez donné un indice pour vérifier dans Storyboard. Et j'ai résolu ma moitié de mon problème.
selva
10

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 illustrant comment il a résolu le problème en plaçant 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 défini sur true par défaut, entraînant une différence entre la conception du storyboard et le simulateur Réglage automatique défini sur true par défaut, entraînant une différence entre la conception du storyboard et le simulateur

Résolu: le code ci-dessus a été appliqué, désactivant le réglage automatique. Code ci-dessus appliqué, désactivant le réglage automatique.

Christopher Wade Cantley
la source
5
si vous activez automatiquementAdjustsScrollViewInsets sur YES, vous devez définir la contrainte supérieure sur superview et non sur topGuideLayout.
xmkevinchen
5

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

self.navigationController.navigationBar.translucent = NO;
user3430340
la source
2

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

  • La vue de VC, ou
  • Première vue secondaire 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 DIY)

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 ajuster manuellement les incrustations de la vue de défilement. Mais s'il vous plaît ne le réglez pas sur constant comme 44 ou 64 ou même 20 comme beaucoup le suggèrent autour de SO. Vous ne pouvez jamais connaître la taille. Il peut y avoir la notification incall / gps / audio, la barre de navigation ne doit pas toujours être de 44 points, etc.

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

Vojta Rujbr
la source
Et évidemment, la barre de navigation est translucide.
Vojta Rujbr