Wyjaśnianie różnicy między automatycznieAdjustsScrollViewInsets, ExtendedLayoutIncludesOpaqueBars, EdgeForExtendedLayout w iOS7

250

Dużo czytałem o przejściu na iOS7.

Nie jestem w stanie uzyskać co te trzy właściwości automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout??

Na przykład próbuję zmusić moje kontrolery widoku do uruchomienia poniżej paska stanu, ale nie jestem w stanie tego osiągnąć.

użytkownik1010819
źródło
5
i dlaczego uważasz, że nie czytałem, że .. Problemem jest to, że nie działa zgodnie z oczekiwaniami, podobnie jak w I nie rozumiał dobrze !! .. to jest to powód?
user1010819
1
Ohhh, źle zrozumiałem, co tam mówiłeś. Nie próbowałem brzmieć protekcjonalnie, po prostu niektórzy ludzie zadają takie pytania i są nowi na stronie, brakuje im oczywistych rozwiązań.
erdekhayser
8
W metodzie viewDidLoad dodaj if ([self respondsToSelector: @selector (edgeForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; co zmusi twój widok do rozpoczęcia poniżej paska stanu.
Nandha

Odpowiedzi:

629

Począwszy od iOS7, kontrolery widoku domyślnie używają układu pełnoekranowego. Jednocześnie masz większą kontrolę nad sposobem, w jaki określa on swoje widoki, a dzieje się to dzięki następującym właściwościom:

edgeForExtendedLayout

Zasadniczo za pomocą tej właściwości można ustawić, które strony widoku można rozszerzyć, aby obejmowały cały ekran. Wyobraź sobie, że wpychasz UIViewControllera UINavigationController. Po ułożeniu widoku tego kontrolera widoku rozpocznie się on tam, gdzie kończy się pasek nawigacji, ale ta właściwość określi, które strony widoku (górny, lewy, dolny, prawy) można rozszerzyć, aby wypełnić cały ekran.

Zobaczmy to na przykładzie:

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

Tutaj nie ustawiasz wartości edgesForExtendedLayout, dlatego przyjmowana jest wartość domyślna ( UIRectEdgeAll), więc widok rozszerza swój układ, aby wypełnić cały ekran.

Oto wynik:

bez krawędzi dla rozszerzonego układu widok wypełnia cały ekran

Jak widać, czerwone tło wystaje za pasek nawigacyjny i pasek stanu.

Teraz ustawisz tę wartość na UIRectEdgeNone, więc mówisz kontrolerowi widoku, aby nie rozszerzał widoku, aby obejmował ekran:

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

A wynik:

z zestawem EdgeForExtendedLayout widok znajduje się tuż pod nawigacją


automatycznieAdjustsScrollViewInsets

Ta właściwość jest używana, gdy widok jest UIScrollViewpodobny lub podobny, na przykład UITableView. Chcesz, aby Twój stół zaczynał się tam, gdzie kończy się pasek nawigacji, ponieważ nie zobaczysz całej zawartości, jeśli nie, ale jednocześnie chcesz, aby stół obejmował cały ekran podczas przewijania. W takim przypadku ustawienie edgesForExtendedLayoutBrak nie będzie działać, ponieważ tabela zacznie się przewijać w miejscu, w którym kończy się pasek nawigacji, i nie będzie się za nim znajdował.

Tutaj przydatna jest ta właściwość. Jeśli pozwolisz, aby kontroler widoku automatycznie dostosowywał wstawki (ustawienie tej właściwości na TAK, również wartość domyślną), doda wstawki na górze tabeli, więc tabela rozpocznie się w miejscu nawigacji pasek się kończy, ale przewijanie obejmie cały ekran.

To jest, gdy jest ustawiony na NIE:

tabela przewinie cały ekran, ale zaczyna się częściowo zakryta

I TAK (domyślnie):

tabela przewija się po całym ekranie i zaczyna się tuż pod nawigacją

W obu przypadkach tabela przewija się za paskiem nawigacji, ale w drugim przypadku (TAK) rozpocznie się od paska nawigacji.


ExtendedLayoutIncludesOpaqueBars

Ta wartość jest tylko dodatkiem do poprzednich. Domyślnie ten parametr jest ustawiony na NIE. Jeśli pasek stanu jest nieprzezroczysty, widoki nie zostaną rozszerzone o pasek stanu, nawet jeśli rozszerzysz widok, aby go zakryć ( edgesForExtendedLayoutdo UIRectEdgeAll).

Jeśli ustawisz wartość na TAK, pozwoli to ponownie przejść do widoku poniżej paska stanu.

Jeśli coś nie jest jasne, napisz komentarz, a ja odpowiem.

Skąd iOS wie, z którego UIScrollView korzystać?

iOS pobiera pierwszy widok podrzędny w widoku ViewController, ten o indeksie 0, a jeśli jest to podklasa, UIScrollViewstosuje do niego wyjaśnione właściwości.

Oczywiście oznacza to, że UITableViewControllerdziała domyślnie (ponieważ UITableViewjest to pierwszy widok).

Antonio MG
źródło
Musimy ustawić te właściwości tylko wtedy, gdy pokazujemy domyślny pasek nawigacyjny, a nie, jeśli jest to dostosowany pasek nawigacyjny, prawda?
Hemang
1
Nie, jeśli używasz paska nawigacji iOS, ale z własnym projektem, musisz użyć tych samych właściwości. Jeśli po prostu utworzysz pasek nawigacji od zera, te właściwości nie będą działać.
Antonio MG
Nie rozumiem, dlaczego w całym widoku pojawia się mała czarnawa warstwa? Proszę pomóż? : /
aZtraL-EnForceR
24
To wyjaśnienie jest o wiele lepsze niż Przewodnik przejścia do interfejsu użytkownika w systemie iOS 7. To powinno po prostu zastąpić przewodnik, co nie miało dla mnie sensu.
Sam
2
Myślę, że ExtendedLayoutIncludesOpaqueBars powinien być domyślnie TAK zamiast NIE. Zmiana kolorów widoku (półprzezroczystość) nie powinna wpływać na układ.
Vladimír Slavík
15

Nie jestem pewien, czy używasz scenorysów, ale jeśli tak, aby Twoje kontrolery widoku zaczynały się poniżej paska stanu (i powyżej dolnego paska):

Wybierz kontroler widoku w IB. W Inspektorze atrybutów usuń zaznaczenie opcji „Wydłuż krawędzie - pod górnymi słupkami” i „Wydłuż krawędzie - pod dolnymi słupkami”.

Ali Beadle
źródło
DOBRZE. Wtedy myślę, że to, co zasugerowała Nandha, osiągnie ten sam wynik programowo. Jeśli nie działa w viewDidLoad, może być konieczne przeniesienie do viewDidLayoutSubviews.
Ali Beadle,
Wskazuje, czy rozszerzony układ zawiera nieprzezroczyste paski. @property (nonatomic, przypis) BOOL ExtendedLayoutIncludesOpaqueBars Dyskusja Wartość domyślna to NIE.
Abdul Yasin
+1, dałeś mi wskazówkę, by sprawdzić w Storyboard. I rozwiązałem połowę mojego problemu.
selva
10

Używam scenariuszy i powyższe porady działały, ale nie byłem do końca pewien, jak je wdrożyć. Poniżej znajduje się krótki przykład szybkiego rozwiązania problemu poprzez wprowadzenie zalecanego rozwiązania do 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.
  }

}

Mój problem: Automatyczna regulacja domyślnie ustawiona na true powoduje różnicę między projektem scenorysu a symulatorem Opcja Auto Adjust domyślnie ustawiona na true powoduje różnicę między projektem scenorysu a symulatorem

Rozwiązane: Zastosowano powyższy kod, wyłączając automatyczną regulację. Zastosowano powyższy kod, wyłączając automatyczne dopasowanie.

Christopher Wade Cantley
źródło
5
jeśli włączysz automatyczneAdjustsScrollViewInsets jako TAK, powinieneś ustawić górne ograniczenie, aby nadzorować, a nie topGuideLayout.
xmkevinchen
5

Rozwiązałem ten problem, dodając ten wiersz, ale mój problem był związany z „ UIViewnie”UIScrollView

self.navigationController.navigationBar.translucent = NO;
użytkownik3430340
źródło
2

Pamiętaj tylko, że automaticallyAdjustsScrollViewInsets właściwość działa tylko wtedy, gdy istnieje widok przewijania (widok tabeli, widok kolekcji ...)

  • Widok VC lub
  • Pierwszy widok tego widoku

Inne sugerują, że nie działa, nawet jeśli jest to pierwszy widok cząstkowy, ale w hierarchii widoków istnieją inne widoki przewijania.

EDYCJA (rozszerzenie DIY)

Jeśli chcesz uzyskać podobne zachowanie, nawet jeśli nie możesz spełnić tych warunków (np. Masz obraz tła poniżej widoku przewijania), możesz ręcznie dopasować wstawki widoku przewijania. Ale proszę nie ustawiać stałej na 44 lub 64, a nawet 20, jak wielu sugeruje wokół SO. Nie możesz nigdy poznać rozmiaru. Może być powiadomienie incall / gps / audio, pasek nawigacyjny nie musi zawsze mieć 44 punktów itp.

Myślę, że najlepszym rozwiązaniem jest użycie layoutGuide lengthw didLayoutSubviews:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

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

Możesz użyć bottomLayoutGuide w ten sam sposób.

Vojta Rujbr
źródło
I oczywiście pasek nawigacji jest półprzezroczysty.
Vojta Rujbr