Erklären des Unterschieds zwischen automatischAnpassungenScrollViewInsets, erweitertes LayoutIncludesOpaqueBars, KantenFürExtendedLayout in iOS7

250

Ich habe viel über den Übergang der iOS7-Benutzeroberfläche gelesen.

Ich bin nicht in der Lage , was diese drei Eigenschaften zu erhalten automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout??

Ich versuche beispielsweise, meine View Controller unterhalb der Statusleiste zu starten, kann dies jedoch nicht erreichen.

user1010819
quelle
5
und warum denkst du, ich habe das nicht gelesen? .. Das Problem ist, dass es nicht wie erwartet funktioniert, da ich es nicht gut verstanden habe !! .. das ist der Grund
user1010819
1
Ohhh, ich habe falsch verstanden, was du dort gesagt hast. Ich habe nicht versucht, bevormundend zu klingen. Es ist nur so, dass einige Leute, die Fragen wie diese stellen und neu auf der Website sind, die offensichtlichen Lösungen verpassen.
Erdekhayser
8
Fügen Sie in Ihrer viewDidLoad-Methode if hinzu ([self responsondsToSelector: @selector (edgeForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; Dadurch wird Ihre Ansicht unterhalb der Statusleiste gestartet.
Nandha

Antworten:

629

Ab iOS7 verwenden die View Controller standardmäßig das Vollbild-Layout. Gleichzeitig haben Sie mehr Kontrolle darüber, wie die Ansichten dargestellt werden. Dies geschieht mit den folgenden Eigenschaften:

KantenForExtendedLayout

Grundsätzlich legen Sie mit dieser Eigenschaft fest, welche Seiten Ihrer Ansicht auf den gesamten Bildschirm erweitert werden können. Stellen Sie sich vor, Sie drücken ein UIViewControllerin ein UINavigationController. Wenn die Ansicht dieses Ansichtscontrollers angelegt ist, beginnt sie dort, wo die Navigationsleiste endet. Mit dieser Eigenschaft wird jedoch festgelegt, welche Seiten der Ansicht (oben, links, unten, rechts) erweitert werden können, um den gesamten Bildschirm auszufüllen.

Lassen Sie es uns anhand eines Beispiels sehen:

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

Hier legen Sie nicht den Wert von fest edgesForExtendedLayout, daher wird der Standardwert ( UIRectEdgeAll) verwendet, sodass die Ansicht ihr Layout erweitert, um den gesamten Bildschirm auszufüllen.

Das ist das Ergebnis:

Ohne Kanten für ein erweitertes Layout füllt die Ansicht den gesamten Bildschirm aus

Wie Sie sehen können, erstreckt sich der rote Hintergrund hinter der Navigationsleiste und der Statusleiste.

Jetzt setzen Sie diesen Wert auf UIRectEdgeNoneund weisen den Ansichts-Controller an, die Ansicht nicht auf den Bildschirm auszudehnen:

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

Und das Ergebnis:

Wenn KantenForExtendedLayout festgelegt ist, befindet sich die Ansicht direkt unter der Navigation


autoAdjustsScrollViewInsets

Diese Eigenschaft wird verwendet, wenn Ihre Ansicht UIScrollViewähnlich oder ähnlich ist, z UITableView. Sie möchten, dass Ihre Tabelle dort beginnt, wo die Navigationsleiste endet, da sonst nicht der gesamte Inhalt angezeigt wird. Gleichzeitig soll Ihre Tabelle beim Scrollen den gesamten Bildschirm abdecken. In diesem Fall edgesForExtendedLayoutfunktioniert die Einstellung " Keine" nicht, da Ihre Tabelle an der Stelle, an der die Navigationsleiste endet, einen Bildlauf durchführt und nicht dahinter steht.

Hier ist diese Eigenschaft nützlich. Wenn Sie den Ansichts-Controller die Einfügungen automatisch anpassen lassen (indem Sie diese Eigenschaft auf JA setzen, auch den Standardwert), werden am oberen Rand der Tabelle Einfügungen hinzugefügt, sodass die Tabelle dort beginnt, wo die Navigation beginnt Die Leiste endet, aber der Bildlauf deckt den gesamten Bildschirm ab.

Dies ist, wenn auf NO gesetzt ist:

Die Tabelle rollt über den gesamten Bildschirm, beginnt jedoch teilweise abgedeckt

Und JA (standardmäßig):

Die Tabelle rollt über den gesamten Bildschirm und beginnt direkt unter der Navigation

In beiden Fällen wird die Tabelle hinter der Navigationsleiste gescrollt, im zweiten Fall (JA) wird sie unterhalb der Navigationsleiste gestartet.


ExtendedLayoutIncludesOpaqueBars

Dieser Wert ist nur eine Ergänzung zu den vorherigen. Standardmäßig ist dieser Parameter auf NO eingestellt. Wenn die Statusleiste undurchsichtig ist, werden die Ansichten nicht um die Statusleiste erweitert, selbst wenn Sie Ihre Ansicht erweitern, um sie abzudecken ( edgesForExtendedLayoutbis UIRectEdgeAll).

Wenn Sie den Wert auf YES setzen, wird die Ansicht wieder unter die Statusleiste verschoben.

Wenn etwas nicht klar ist, schreibe einen Kommentar und ich werde ihn beantworten.

Woher weiß iOS, welches UIScrollView verwendet werden soll?

iOS greift auf die erste Unteransicht in der Ansicht Ihres ViewControllers zu, die am Index 0, und wenn es sich um eine Unterklasse von handelt UIScrollView, werden die erläuterten Eigenschaften darauf angewendet .

Dies bedeutet natürlich, dass dies UITableViewControllerstandardmäßig funktioniert (da dies UITableViewdie erste Ansicht ist).

Antonio MG
quelle
Wir müssen diese Eigenschaften nur festlegen, wenn die Standardnavigationsleiste angezeigt wird und nicht, wenn die angepasste Navigationsleiste angezeigt wird, oder?
Hemang
1
Nein, wenn Sie die iOS-Navigationsleiste verwenden, aber Ihr eigenes Design haben, müssen Sie dieselben Eigenschaften verwenden. Wenn Sie Ihre Navigationsleiste nur von Grund auf neu erstellen, funktionieren diese Eigenschaften nicht.
Antonio MG
Ich verstehe nicht, warum es eine kleine schwärzliche Schicht über der gesamten Ansicht gibt? Bitte helfen Sie? : /
aZtraL-EnForceR
24
Diese Erklärung ist viel besser als das iOS 7 UI Transition Guide. Dies sollte nur die Anleitung ersetzen, was für mich keinen Sinn ergab.
Sam
2
Ich denke, extendedLayoutIncludesOpaqueBars sollte standardmäßig YES anstelle von NO sein. Das Ändern der Ansichtsfarben (Transluzenz) sollte das Layout nicht beeinflussen.
Vladimír Slavík
15

Sie sind sich nicht sicher, ob Sie Storyboards verwenden, aber wenn ja, damit Ihre View Controller unterhalb der Statusleiste (und oberhalb der unteren Leiste) beginnen:

Wählen Sie den Ansichts-Controller in IB aus. Deaktivieren Sie im Attributinspektor die Option "Kanten erweitern - unter den oberen Balken" und "Kanten erweitern - unter den unteren Balken".

Ali Beadle
quelle
OK. Dann denke ich, dass das, was Nandha oben vorgeschlagen hat, programmatisch das gleiche Ergebnis erzielen wird. Wenn es unter viewDidLoad nicht funktioniert, muss es möglicherweise nach viewDidLayoutSubviews verschoben werden.
Ali Beadle
Gibt an, ob das erweiterte Layout undurchsichtige Balken enthält. @property (nichtatomar, zuweisen) BOOL extendedLayoutIncludesOpaqueBars Diskussion Der Standardwert ist NO.
Abdul Yasin
+1, Du hast mir einen Hinweis gegeben, wie ich im Storyboard einchecken soll. Und ich habe meine Hälfte meines Problems gelöst.
Selva
10

Ich verwende Storyboards und die oben genannten Ratschläge haben funktioniert, aber ich war mir nicht ganz sicher, wie ich sie implementieren soll. Im Folgenden finden Sie ein kurzes Beispiel, wie das Problem durch Einfügen der empfohlenen Lösung in den ViewController behoben werden kann.

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.
  }

}

Mein Problem: Die automatische Anpassung ist standardmäßig auf true gesetzt, was zu einem Unterschied zwischen Storyboard-Design und Simulator führt Die automatische Anpassung ist standardmäßig auf true gesetzt, was zu einem Unterschied zwischen Storyboard-Design und Simulator führt

Behoben: Der oben angegebene Code wurde angewendet und die automatische Anpassung deaktiviert. Der oben angegebene Code schaltet die automatische Anpassung aus.

Christopher Wade Cantley
quelle
5
Wenn Sie die automatischAnpassungenScrollViewInsets als JA aktivieren, sollten Sie die oberste Einschränkung so festlegen, dass nicht das topGuideLayout angezeigt wird.
Xmkevinchen
5

Ich habe dieses Problem durch Hinzufügen dieser Zeile gelöst, aber mein Problem bezog sich auf a UIView, nichtUIScrollView

self.navigationController.navigationBar.translucent = NO;
user3430340
quelle
2

Denken Sie automaticallyAdjustsScrollViewInsets nur daran, dass die Eigenschaft nur funktioniert, wenn eine Bildlaufansicht (Tabellenansicht, Sammlungsansicht, ...) vorhanden ist

  • Die Ansicht von VC oder
  • Erste Unteransicht dieser Ansicht

Andere schlugen vor, dass es auch dann funktioniert, wenn es sich um die erste Unteransicht handelt, aber es gibt andere Bildlaufansichten in der Ansichtshierarchie.

EDIT (Erweiterung DIY)

Wenn Sie ein ähnliches Verhalten wünschen, auch wenn Sie diese Bedingungen nicht erfüllen können (z. B. wenn Sie ein Hintergrundbild unter der Bildlaufansicht haben), können Sie die Bildlaufansichten manuell anpassen. Aber bitte setzen Sie es nicht auf konstant wie 44 oder 64 oder sogar 20, wie viele um SO vorschlagen. Sie können die Größe nie kennen. Es kann eine Incall / GPS / Audio-Benachrichtigung geben, die Navigationsleiste muss nicht immer 44 Punkte usw. enthalten.

Ich denke, die beste Lösung ist die Verwendung von layoutGuide lengthin didLayoutSubviews:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

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

Sie können den bottomLayoutGuide auf die gleiche Weise verwenden.

Vojta Rujbr
quelle
Und offensichtlich ist die Navigationsleiste durchscheinend.
Vojta Rujbr