Spiegazione della differenza tra automaticAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgeForExtendedLayout in iOS7


250

Ho letto molto sulla transizione dell'interfaccia utente di iOS7.

Io non sono in grado di ottenere ciò che queste tre proprietà automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout??

Ad esempio, sto cercando di avviare i controller della vista sotto la barra di stato ma non riesco a raggiungerlo.


5
e perché pensi di non averlo letto? .. Il problema è che non funziona come previsto, perché non l'ho capito bene !! .. questo è il motivo
user1010819

1
Ohhh ho capito male quello che stavi dicendo lì. Non stavo cercando di sembrare condiscendente, è solo che quando alcune persone fanno domande come questa e sono nuove al sito, mancano le soluzioni ovvie.
erdekhayser,

8
Nel tuo metodo viewDidLoad, aggiungi if ([self respondsToSelector: @selector (edgeForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; che costringerà la visualizzazione a iniziare sotto la barra di stato.
Nandha,

Risposte:


629

A partire da iOS7, i controller di visualizzazione utilizzano il layout a schermo intero per impostazione predefinita. Allo stesso tempo, hai un maggiore controllo sul modo in cui espone le sue viste, e questo è fatto con quelle proprietà:

edgesForExtendedLayout

Fondamentalmente, con questa proprietà si imposta quali lati della vista possono essere estesi per coprire l'intero schermo. Immagina di spingere a UIViewControllerin a UINavigationController. Quando la vista di quel controller di vista è disposta, inizierà dove finisce la barra di navigazione, ma questa proprietà imposterà quali lati della vista (in alto, a sinistra, in basso, a destra) possono essere estesi per riempire l'intero schermo.

Vediamolo con un esempio:

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

Qui non stai impostando il valore di edgesForExtendedLayout, quindi viene preso il valore predefinito ( UIRectEdgeAll), quindi la vista estende il suo layout per riempire l'intero schermo.

Questo è il risultato:

senza bordi per un layout esteso, la vista riempie l'intero schermo

Come puoi vedere, lo sfondo rosso si estende dietro la barra di navigazione e la barra di stato.

Ora imposterai quel valore su UIRectEdgeNone, quindi stai dicendo al controller di visualizzazione di non estendere la vista per coprire lo schermo:

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

E il risultato:

con edgeForExtendedLayout impostato, la vista è appena sotto la navigazione


automaticallyAdjustsScrollViewInsets

Questa proprietà viene utilizzata quando la vista è UIScrollViewsimile o simile, ad esempio a UITableView. Volete che la vostra tabella inizi dove finisce la barra di navigazione, perché non vedrete l'intero contenuto in caso contrario, ma allo stesso tempo volete che la vostra tabella copra l'intero schermo durante lo scorrimento. In tal caso, l'impostazione edgesForExtendedLayoutsu Nessuno non funzionerà perché la tabella inizierà a scorrere dove finisce la barra di navigazione e non andrà dietro di essa.

Qui è dove questa proprietà è utile, se si lascia che il controller di visualizzazione regoli automaticamente gli inserti (impostando questa proprietà su SÌ, anche il valore predefinito), verranno aggiunti gli inserti nella parte superiore della tabella, quindi la tabella inizierà dove la navigazione la barra termina, ma lo scorrimento coprirà l'intero schermo.

Questo è quando è impostato su NO:

la tabella scorrerà su tutto lo schermo, ma inizia parzialmente coperta

E SÌ (per impostazione predefinita):

la tabella scorre su tutto lo schermo e inizia appena sotto la navigazione

In entrambi i casi, la tabella scorre dietro la barra di navigazione, ma nel secondo caso (SÌ), inizierà da sotto la barra di navigazione.


extendedLayoutIncludesOpaqueBars

Questo valore è solo un'aggiunta ai precedenti. Per impostazione predefinita, questo parametro è impostato su NO. Se la barra di stato è opaca, le viste non verranno estese per includere la barra di stato, anche se si estende la vista per coprirla ( edgesForExtendedLayouta UIRectEdgeAll).

Se si imposta il valore su SÌ, ciò consentirà alla vista di tornare di nuovo sotto la barra di stato.

Se qualcosa non è chiaro, scrivi un commento e risponderò.

Come fa iOS a sapere cosa usare UIScrollView?

iOS prende la prima sottoview nella vista di ViewController, quella nell'indice 0, e se si tratta di una sottoclasse di UIScrollViewallora applica le proprietà spiegate.

Ovviamente, ciò significa che UITableViewControllerfunziona per impostazione predefinita (poiché UITableViewè la prima vista).


Dobbiamo impostare queste proprietà solo se, stiamo mostrando la barra di navigazione predefinita, e non se la sua barra di navigazione personalizzata, giusto?
Hemang,

1
No, se usi la barra di navigazione iOS ma con il tuo design dovrai usare le stesse proprietà. Se crei semplicemente la barra di navigazione da zero, tali proprietà non funzioneranno.
Antonio MG,

Non capisco perché ci sia un piccolo strato nerastro su tutta la vista? Per favore aiuto? : /
aZtraL-EnForceR

24
Questa spiegazione è molto meglio della Guida alla transizione dell'interfaccia utente di iOS 7. Questo dovrebbe semplicemente sostituire la guida, il che non ha senso per me.
Sam,

2
Penso che extendedLayoutIncludesOpaqueBars dovrebbe essere SÌ per impostazione predefinita anziché NO. La modifica dei colori della vista (traslucenza) non dovrebbe influire sul layout.
Vladimír Slavík,

15

Non sei sicuro di utilizzare gli storyboard, ma se lo sei, per far iniziare i controller della vista sotto la barra di stato (e sopra la barra in basso):

Seleziona il controller di visualizzazione in IB, Nella finestra di ispezione degli attributi, deseleziona "Estendi bordi - Sotto le barre superiori" e "Estendi bordi - Sotto le barre inferiori".


OK. Quindi penso che ciò che Nandha ha suggerito sopra otterrà lo stesso risultato a livello di programmazione. Se non funziona con viewDidLoad, potrebbe essere necessario spostarlo in viewDidLayoutSubviews.
Ali Beadle,

Indica se il layout esteso include o meno barre opache. @property (nonatomic, assegnato) BOOL extendedLayoutIncludesOpaqueBars Discussione Il valore predefinito è NO.
Abdul Yasin,

+1, mi hai dato un suggerimento per controllare in Storyboard. E ho risolto la mia metà del mio problema.
selva,

10

Sto usando gli storyboard e usando i consigli di cui sopra ha funzionato, ma non ero esattamente sicuro su come implementarlo. Di seguito è riportato un breve esempio di come è stato risolto il problema inserendo la soluzione consigliata in 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.
  }

}

Il mio problema: la regolazione automatica è impostata su true per impostazione predefinita, causando una differenza tra il design dello storyboard e il simulatore La regolazione automatica è impostata su true per impostazione predefinita, causando una differenza tra il design dello storyboard e il simulatore

Risolto: codice sopra applicato, disattivazione della regolazione automatica. Codice sopra applicato, disattivazione della regolazione automatica.


5
se si attiva automaticamenteAdjustsScrollViewInsets come YES, è necessario impostare il vincolo principale in modo da non visualizzare topGuideLayout.
xmkevinchen,

5

Ho risolto questo problema aggiungendo questa riga, ma il mio problema era legato a un UIView, noUIScrollView

self.navigationController.navigationBar.translucent = NO;

2

Basta tenere presente che la automaticallyAdjustsScrollViewInsets proprietà funziona solo se è presente un tipo di vista di scorrimento (vista tabella, vista raccolta, ...)

  • La vista di VC, o
  • Prima visione d'insieme di questa vista

Altri hanno suggerito che funzioni anche se è la prima sottoview, ma ci sono altre viste di scorrimento nella gerarchia delle viste.

EDIT (estensione DIY)

Se si desidera un comportamento simile anche se non è possibile soddisfare queste condizioni (ad esempio, si ha un'immagine di sfondo sotto la vista di scorrimento), è possibile regolare manualmente gli inserti della vista di scorrimento. Ma per favore non impostarlo su costante come 44 o 64 o addirittura 20 come molti suggeriscono in SO. Non puoi mai conoscere le dimensioni. Possono esserci notifiche di chiamata / gps / audio, la barra di navigazione non deve sempre essere 44 punti ecc.

Penso che la soluzione migliore sia usare layoutGuide lengthin didLayoutSubviews:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

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

Puoi usare bottomLayoutGuide allo stesso modo.


E ovviamente la barra di navigazione è traslucida.
Vojta Rujbr,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.