Die Statusleiste und die Navigationsleiste werden in iOS 7 über den Grenzen meiner Ansicht angezeigt

435

Ich habe kürzlich Xcode 5 DP heruntergeladen , um meine Apps in iOS 7 zu testen. Als erstes habe ich festgestellt und bestätigt, dass die Größe meiner Ansicht nicht immer geändert wird, um die Statusleiste und die Navigationsleiste zu berücksichtigen.

In viewDidLayoutSubviewsdrucke ich die Grenzen der Ansicht:

{{0, 0}, {320, 568}}

Dies führt dazu, dass mein Inhalt unter der Navigationsleiste und der Statusleiste angezeigt wird.

Ich weiß, dass ich die Höhe selbst erklären kann, indem ich die Höhe des Hauptbildschirms erhalte, die Höhe der Statusleiste und die Höhe der Navigationsleiste subtrahiere, aber das scheint unnötige zusätzliche Arbeit zu sein.

Wie kann ich dieses Problem beheben?

Aktualisieren:

Ich habe eine Lösung für dieses spezielle Problem gefunden. Setzen Sie die durchscheinende Eigenschaft der Navigationsleiste auf NO:

self.navigationController.navigationBar.translucent = NO;

Dadurch wird verhindert, dass die Ansicht unter der Navigationsleiste und der Statusleiste eingerahmt wird.

Ich habe jedoch keine Lösung für den Fall gefunden, dass die Navigationsleiste durchscheinend sein soll. Wenn Sie beispielsweise ein Foto im Vollbildmodus anzeigen, möchte ich, dass die Navigationsleiste durchscheinend ist und die Ansicht darunter eingerahmt wird. Das funktioniert, aber wenn ich die Navigationsleiste ein- oder ausblende, habe ich noch seltsamere Ergebnisse erzielt. Bei der ersten Unteransicht (einer UIScrollView) werden die Grenzen und der Ursprung jedes Mal geändert.

Beebcon
quelle
Ich bekomme auch das gleiche Problem in Xcode 5 DP
Gopesh Gupta
Lassen Sie mich wissen, ob Sie eine Lösung bekommen
Gopesh Gupta
1
Suchen Sie in der Navigationsleiste nach einer Farbfarbeigenschaft. Sie sollten in der Lage sein, diese blaue Farbe nach Ihren Wünschen zu ändern.
Beebcon
9
Ich hasse es, ios manchmal zu aktualisieren, weil Apple Ihnen nie die Möglichkeit gegeben hat, Ihre App abwärtskompatibel zu halten.
Bagusflyer
3
Wenn das Problem mit der Ansicht in der Statusleiste zusammenhängt, nachdem die obere Leiste des Navigationscontrollers ausgeblendet wurde, würde ich auf die Antwort von @Stunner stackoverflow.com/a/18976660/235206 als Lösung
verweisen

Antworten:

495

Sie können dies erreichen, indem Sie eine neue Eigenschaft implementieren, die edgesForExtendedLayoutim iOS7 SDK aufgerufen wird. Bitte fügen Sie den folgenden Code hinzu, um dies zu erreichen:

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

Sie müssen das oben Genannte in Ihre -(void)viewDidLoadMethode aufnehmen.

iOS 7 bringt verschiedene Änderungen am Layout und der Anpassung des Erscheinungsbilds Ihrer Benutzeroberfläche mit sich . Die Änderungen im Layout, in der Farbtonfarbe und in der Schriftart des View-Controllers wirken sich auf alle UIKit- Objekte in Ihrer App aus. Darüber hinaus bieten Verbesserungen der Gestenerkennungs-APIs eine genauere Kontrolle über Gesteninteraktionen.

View Controller verwenden

In iOS 7 verwenden View Controller das Vollbild-Layout. Gleichzeitig bietet Ihnen iOS 7 eine genauere Kontrolle darüber, wie ein Ansichts-Controller seine Ansichten anordnet. Insbesondere wurde das Konzept des Vollbild-Layouts verfeinert, damit ein Ansichts-Controller das Layout jeder Kante seiner Ansicht festlegen kann.

Die wantsFullScreenLayoutView Controller-Eigenschaft ist in iOS 7 veraltet. Wenn Sie derzeit angeben wantsFullScreenLayout = NO, zeigt der View Controller seinen Inhalt möglicherweise an einem unerwarteten Bildschirmort an, wenn er in iOS 7 ausgeführt wird.

UIViewController Folgende Eigenschaften stehen zur Verfügung, um anzupassen, wie ein Ansichtscontroller seine Ansichten anordnet:

  • KantenForExtendedLayout

Die edgesForExtendedLayoutEigenschaft verwendet den UIRectEdgeTyp, der jede der vier Kanten eines Rechtecks ​​angibt und zusätzlich keine und alle angibt. Verwenden Sie edgesForExtendedLayoutdiese Option, um anzugeben, welche Kanten einer Ansicht unabhängig von der Balkentransparenz erweitert werden sollen. Standardmäßig ist der Wert dieser Eigenschaft UIRectEdgeAll.

  • ExtendedLayoutIncludesOpaqueBars

Wenn Ihr Design undurchsichtige Balken verwendet, verfeinern Sie dies, edgesForExtendedLayoutindem Sie die extendedLayoutIncludesOpaqueBarsEigenschaft ebenfalls auf NO setzen . (Der Standardwert von extendedLayoutIncludesOpaqueBarsist NO .)

  • autoAdjustsScrollViewInsets

Wenn Sie nicht möchten, dass die Inhaltseinfügungen einer Bildlaufansicht automatisch angepasst werden, setzen Sie automaticallyAdjustsScrollViewInsetsauf NEIN . (Der Standardwert von automaticallyAdjustsScrollViewInsetsist JA .)

  • topLayoutGuide, bottomLayoutGuide

Die Eigenschaften topLayoutGuideund bottomLayoutGuidegeben die Position der oberen oder unteren Balkenkanten in der Ansicht eines Ansichtscontrollers an. Wenn sich Balken oben oder unten in einer Ansicht überlappen sollen, können Sie die Ansicht mit dem Interface Builder relativ zur Leiste positionieren, indem Sie Einschränkungen am unteren topLayoutGuideoder oberen Rand von bottomLayoutGuide erstellen. (Wenn keine Balken die Ansicht überlappen sollten, entspricht der untere Rand topLayoutGuidedem oberen Rand der Ansicht und der obere bottomLayoutGuideRand dem unteren Rand der Ansicht.) Beide Eigenschaften werden auf Anforderung träge erstellt.

Bitte beziehen Sie sich auf Apple Doc

Nandha
quelle
2
Es wird nicht unter iOS6 kompiliert. Ich denke, es sollte als
Performselector
8
Ja, deshalb habe ich die Auswahlprüfung mit if-Bedingung aufgenommen, wenn ([self replyToSelector: @selector (edgeForExtendedLayout)])
Nandha
19
Dies würde nicht funktionieren, wenn ich keine Navigationsleiste habe. In diesem Fall erstreckt sich meine Ansicht hinter der Statusleiste.
Van Du Tran
4
Ich habe das gleiche Problem wie @VanDuTran. KantenForExtendedLayout hilft nicht, wenn die Navigationsleiste ausgeblendet ist.
fishinear
6
es funktioniert, aber ... es gibt keinen durchscheinenden Effekt mehr ... wie können wir auch den durchscheinenden Effekt bewahren ...
Dipu Rajak
110

Sie müssen nicht berechnen, wie weit Sie alles nach unten verschieben müssen, dafür gibt es eine eingebaute Eigenschaft. Markieren Sie im Interface Builder Ihren Ansichtscontroller und navigieren Sie zum Attributinspektor. Hier sehen Sie einige Kontrollkästchen neben den Worten "Kanten verlängern". Wie Sie sehen können, wird im ersten Screenshot standardmäßig der Inhalt unter den oberen und unteren Balken angezeigt, jedoch nicht unter den undurchsichtigen Balken. Daher hat es für Sie funktioniert, den Balkenstil auf nicht durchscheinend einzustellen.

Wie Sie im ersten Screenshot sehen können, verstecken sich zwei UI-Elemente unter der Navigationsleiste. (Ich habe Wireframes in IB aktiviert, um dies zu veranschaulichen.) Bei diesen Elementen, einem UIButton und einem UISegmentedControl, ist der Ursprung "y" auf Null gesetzt, und der Ansichts-Controller ist so eingestellt, dass Inhalte unterhalb der oberen Leiste zulässig sind.

Geben Sie hier die Bildbeschreibung ein

Dieser zweite Screenshot zeigt, was passiert, wenn Sie das Kontrollkästchen "Unter den oberen Balken" deaktivieren. Wie Sie sehen können, wurde die Ansicht der Ansichtssteuerung entsprechend nach unten verschoben, damit sich ihr y-Ursprung direkt unter der Navigationsleiste befindet.

Geben Sie hier die Bildbeschreibung ein

Dies kann auch programmgesteuert durch die Verwendung von erreicht werden -[UIViewController edgesForExtendedLayout]. Hier ist ein Link zur Klassenreferenz für edgeForExtendedLayout und für UIRectEdge

[self setEdgesForExtendedLayout:UIRectEdgeNone];
Mick MacCallum
quelle
15
Wie mache ich dasselbe für die Ansicht in einer .xib?
Bobics
2
Ich habe ein Etikett hinzugefügt und bin Ihren Anweisungen gefolgt, aber das funktioniert bei mir nicht
RMRAHUL
5
@bobics Die Antwort auf die XIB-Frage lautet: "Das kannst du nicht." Jedenfalls nicht durch IB. Legen Sie ein Radar ab und hoffen Sie, dass Apple es irgendwann anspricht.
Memmons
Danke @ 0x7fffffff, Dies war nur die Information, die ich gesucht habe und die sehr hilfreich war.
Campo
33

Ich habe meine Ansicht programmgesteuert erstellt und dies hat für mich funktioniert:

- (void) viewDidLayoutSubviews {
    // only works for iOS 7+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;

        // snaps the view under the status bar (iOS 6 style)
        viewBounds.origin.y = topBarOffset * -1;

        // shrink the bounds of your view to compensate for the offset
        viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
        self.view.bounds = viewBounds;
    }
}

Quelle (im Abschnitt topLayoutGuide unten auf Seite 39).

Stunner
quelle
Endlich eine Antwort gefunden, die tatsächlich dafür funktioniert. Gute Arbeit!
StuartM
1
Um das Problem zu lösen, dass die Ansicht des Ansichtscontrollers unter der Statusleiste angezeigt wird, wenn die Navigationsleiste ausgeblendet ist, ist dies der Code, der die Ansicht unter der Statusleiste einrastet.
MiKL
Hinweis: Dadurch wird der untere Rand Ihrer Ansicht vom Bildschirm verschoben.
Memmons
1
Auch wenn Sie für bauen nur iOS7, der obige Code wird einen Fehler werfen - topLayoutGuideist iOS7 nur.
Memmons
1
Beachten Sie auch, dass wenn Ihre Hauptansicht eine UITableView ist, die viewDidLayoutSubviews bei jedem Bildlauf aufgerufen werden. Ihr UITableView wird verkleinert, bis seine Höhe 15px beträgt. Fügen Sie ein Flag hinzu, um diesen Code nur einmal auszuführen. ;)
Thomas Johannesmeyer
30

Swift 3 / Swift 4-Lösung, die auch mit NIBs / XIB-Dateien in iOS 10+ funktioniert:

override func viewDidLoad() {
    super.viewDidLoad()

    edgesForExtendedLayout = []
}
flo_23
quelle
Das hat mir geholfen ... So einfach. Danke :-)
Hernan Arber
Vielen Dank, es ist wirklich hilfreich
Muhammad Ahmed Baig
Dies ist die beste Lösung für 10.x Swift 3+ IMO
Shokaveli
10

Wenn die Ansicht die durchscheinende Navigationsleiste haben soll (was irgendwie nett ist), müssen Sie ein contentInset oder ähnliches einrichten.

So mache ich das:

// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) {
      CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
      float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;

      myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);
}
Magnus
quelle
3
warum kannst du es nicht direkt mit 7.0 vergleichen
Leena
1
lol Ich verstehe: Die Überprüfung gegen eine bestimmte Version mit geringfügigem Zusatz ist weniger robust. Aber Sie prüfen, ob der Wert GRÖSSER oder gleich ist. Ein Vergleich mit 7.0 würde hier gut tun;)
EeKay
1
@leena - Dies ist eine Funktion in 7.x und höher - daher überprüfe ich, ob die Version 7 oder höher ist, und überspringe die geringfügigen Änderungen in der Prüfung.
Magnus
2
Ich hatte ein Problem mit meiner tableView, die hinter meiner Tabbar angezeigt wurde. Dadurch wurde die letzte Zeile meiner Tabelle nie über die Registerkartenleiste gescrollt. Ich habe es so behoben: myTableView.contentInset = UIEdgeInsetsMake (0, 0.0, TabbarHeight, 0)
James Laurenstin
contentInsetist eine Eigenschaft von UIScrollView. Was passiert , wenn meine Hauptansicht ist keine Unterklasse von UIScrollView. Wie würde ich dann das Überlappungsproblem beheben?
Pwner
9

edgesForExtendedLayoutmacht den Trick für iOS 7. Wenn Sie die App jedoch über das iOS 7 SDK erstellen und in iOS 6 bereitstellen, wird die Navigationsleiste durchscheinend und die Ansichten darunter angezeigt. Gehen Sie folgendermaßen vor, um das Problem sowohl für iOS 7 als auch für iOS 6 zu beheben:

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific
Raj Pawan Gumdal
quelle
9

Fügen Sie in der Plist-Datei Ihrer Apps eine Zeile hinzu, nennen Sie sie "Controller-basiertes Erscheinungsbild der Statusleiste anzeigen" und setzen Sie sie auf NO .

Idan
quelle
7

Der einfachste Trick besteht darin, die NIB- Datei zu öffnen und diese beiden einfachen Schritte auszuführen:

  1. Schalten Sie das einfach um und stellen Sie es auf das ein, das Sie bevorzugen:

Geben Sie hier die Bildbeschreibung ein

  1. Wählen Sie die UIViews / UIIMageViews / ... aus, die nach unten verschoben werden sollen. In meinem Fall wurde nur das Logo überlappt und ich habe das Delta auf +15 gesetzt. (ODER -15, wenn Sie in Schritt 1 iOS 7 ausgewählt haben)

Geben Sie hier die Bildbeschreibung ein

Und das Ergebnis :

Vor Nach

Riskov
quelle
6
Es funktioniert, aber dies scheint eine schwer zu wartende Lösung zu sein. Es ist am besten, das Problem einfach zu beheben, anstatt es zu patchen.
NLemay
Es ist am besten, es programmgesteuert für alle Unteransichten der Ansicht zu tun, da es nicht funktioniert, wenn es auf die Hauptansicht angewendet wird
Wildmonkey
5

Schnelle Lösung:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None
}
fatihyildizhan
quelle
4
Dies ist jetzt KantenForExtendedLayout = []
Leon
1
Da dies eine öffentliche Antwort ist, sollten wir nicht vergessen anzurufen:super.viewWillAppear(animated)
Prodos
4

Ich möchte Stunners Antwort erweitern und eine hinzufügen if Erklärung zu überprüfen, ob es sich um iOS-7 handelt, da meine App beim Testen unter iOS 6 abstürzen würde.

Der Zusatz würde hinzufügen:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

Daher würde ich vorschlagen, diese Methode zu Ihrer MyViewControler.mDatei hinzuzufügen :

- (void) viewDidLayoutSubviews {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;
        viewBounds.origin.y = topBarOffset * -1;
        self.view.bounds = viewBounds;
    }
}
werdsackjon
quelle
4

Swift 3

override func viewWillAppear(_ animated: Bool) {
    self.edgesForExtendedLayout = []
}
Shahrukh
quelle
3

Ich habe ein Szenario, in dem ich den von Apple geschriebenen BannerViewController zum Anzeigen meiner Anzeigen und einen in den BannerViewController eingebetteten ScrollViewController verwende.

Um zu verhindern, dass die Navigationsleiste meinen Inhalt verbirgt, musste ich zwei Änderungen vornehmen.

1) Ändern Sie BannerViewController.m

- (void)viewDidLoad
{
   [super viewDidLoad];
   float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
   if (systemVersion >= 7.0) {
      self.edgesForExtendedLayout = UIRectEdgeNone;
   }
}

2) Ändern Sie meinen ScrollViewContoller

- (void)viewDidLoad
{
    [super viewDidLoad];
    float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (systemVersion >= 7.0) {
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

Jetzt werden die Anzeigen am unteren Rand der Ansicht korrekt angezeigt, anstatt von der Navigationsleiste abgedeckt zu werden, und der Inhalt oben wird nicht abgeschnitten.

Xavier John
quelle
2

Stellen Sie einfach den folgenden Code in der Ansicht ein.

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
 }
Amit Shelgaonkar
quelle
Dies ist das einzige, was unter meinen Umständen funktioniert hat.
Goobliata
2

Machen Sie eine Einschränkung für das Top-Layout wie folgt Geben Sie hier die Bildbeschreibung ein

carmen_munich
quelle
2

Swift 4.2 - Xcode 10.0 - iOS 12.0:

if #available(iOS 11.0, *) {} else {
  self.edgesForExtendedLayout = []
  self.navigationController?.view.backgroundColor = .white
}
juliancadi
quelle
1

Für mich besteht die einfachste Lösung darin, zwei Schlüssel in die Liste aufzunehmen

Geben Sie hier die Bildbeschreibung ein

giuseppe
quelle
+1, ich hatte die "Statusleiste anfangs ausgeblendet" = JA, aber beim Hinzufügen von "View Controller-basiertes Statusleisten-Erscheinungsbild" = NEIN wurde die Statusleiste entfernt.
Jonas Byström
1

Fügen Sie den Schlüssel "View Controller-basiertes Erscheinungsbild der Statusleiste" aus der Dropdown-Liste als Zeile in hinzu info.plist. Etwas wie das:

Geben Sie hier die Bildbeschreibung ein

Kursat Turkay
quelle
interessant.es hat bei meinen cocos2d-Projekten geholfen. Wenn ich diese Option umschalte, kann ich sehen, dass die obere Statusleiste vollständig verschwunden ist oder angezeigt wird.
Kursat Turkay
1

Ich hatte das gleiche Problem mit meiner App von iPads (armv7, armv7s, amr64), nur indem ich einen anderen UIViewController präsentierte und nach dessen Entlassung die Navigationsleiste unter der Statusleiste angezeigt wird ... Ich verbringe viel Zeit damit, eine Lösung dafür zu finden. Ich verwende Storyboard und in InterfaceBuilder für UIViewController, was schrecklich macht. Ich habe Presentation from FullScreen -> Current Context eingestellt und dieses Problem behoben. Es funktioniert in meiner App nur für iPads => iOS8.0 (Testen mit iOS8.1) und für iPads mit iOS 7.1 funktioniert es nicht !!siehe Screenshot

Alexej W.
quelle
In meinem Fall überlappte meine Hauptansicht meine TabBar und ich hatte keine Ahnung warum. Es stellte sich heraus, dass die Option Kanten verlängern> Unter den unteren Balken aktiviert war. Es war wirklich schwer zu bemerken, da der Hintergrund meiner App weiß war und nur eine gewisse Deckkraft über meiner Registerkartenleiste erzeugt wurde. Vielen Dank!
Jesus Rodriguez
0

Schritte zum Ausblenden der Statusleiste in iOS 7:

1.Gehen Sie zu Ihrer Anwendungsinfo.plist-Datei.

2.Und Set, View Controller-basiertes Statusleisten-Erscheinungsbild: Boolean NO

Hoffe, ich habe das Problem mit der Statusleiste gelöst .....

Chandrika
quelle
0

In meinem Fall wurde loadView () unterbrochen
diesen Code : self.edgesForExtendedLayout = UIRectEdgeNone

aber nach dem Löschen von loadView () hat alles gut funktioniert

DevB2F
quelle