La barra di stato e la barra di navigazione vengono visualizzate oltre i limiti della mia vista in iOS 7


435

Di recente ho scaricato Xcode 5 DP per testare le mie app in iOS 7. La prima cosa che ho notato e confermato è che i limiti della mia vista non vengono sempre ridimensionati per tenere conto della barra di stato e della barra di navigazione.

In viewDidLayoutSubviews, stampo i limiti della vista:

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

Ciò comporta la visualizzazione dei miei contenuti sotto la barra di navigazione e la barra di stato.

So che potrei rendere conto dell'altezza da solo ottenendo l'altezza della schermata principale, sottraendo l'altezza della barra di stato e l'altezza della barra di navigazione, ma sembra un lavoro extra inutile.

Come posso risolvere questo problema?

Aggiornare:

Ho trovato una soluzione per questo problema specifico. Impostare la proprietà traslucida della barra di navigazione su NO:

self.navigationController.navigationBar.translucent = NO;

Ciò consentirà di evitare che la vista venga inquadrata sotto la barra di navigazione e la barra di stato.

Tuttavia, non ho trovato una soluzione per il caso in cui si desidera che la barra di navigazione sia traslucida. Ad esempio, visualizzando una foto a schermo intero, desidero avere la barra di navigazione traslucida e la vista da incorniciare al di sotto di essa. Funziona, ma quando abilito a mostrare / nascondere la barra di navigazione, ho riscontrato risultati ancora più strani. La prima sottoview (un UIScrollView) ottiene i suoi limiti e l'origine cambia ogni volta.


Ricevo anche lo stesso problema in xcode 5 DP
Gopesh Gupta,

Fammi sapere se otterrai qualche soluzione
Gopesh Gupta,

1
Cerca nella barra di navigazione una proprietà del colore della tinta, dovresti essere in grado di cambiare quel colore blu con quello che vuoi.
Beebcon,

9
Odio l'aggiornamento di iOS a volte perché Apple non ti ha mai dato l'opportunità di mantenere la tua app retrocompatibile.
Bagusflyer,

3
Se il problema è legato alla vista andare sotto la barra di stato dopo aver nascosto la barra di controllo di navigazione superiore vorrei fare riferimento alla risposta da @Stunner stackoverflow.com/a/18976660/235206 come la soluzione
Mikl

Risposte:


495

Puoi raggiungere questo obiettivo implementando una nuova proprietà chiamata edgesForExtendedLayoutin iOS7 SDK. Aggiungi il seguente codice per raggiungere questo obiettivo,

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

Devi aggiungere quanto sopra nel tuo -(void)viewDidLoadmetodo.

iOS 7 apporta diverse modifiche al layout e alla personalizzazione dell'aspetto dell'interfaccia utente . Le modifiche al layout del controller di visualizzazione, al colore della tinta e al carattere influiscono su tutti gli oggetti UIKit nella tua app. Inoltre, i miglioramenti apportati alle API di riconoscimento gesti offrono un controllo più preciso delle interazioni gestuali.

Utilizzo dei controller di visualizzazione

In iOS 7, i controller di visualizzazione utilizzano il layout a schermo intero. Allo stesso tempo, iOS 7 ti offre un controllo più granulare sul modo in cui un controller di visualizzazione espone le sue visualizzazioni. In particolare, il concetto di layout a schermo intero è stato perfezionato per consentire a un controller di visualizzazione di specificare il layout di ciascun bordo della vista.

La wantsFullScreenLayoutproprietà del controller di visualizzazione è obsoleta in iOS 7. Se si specifica attualmente wantsFullScreenLayout = NO, il controller di visualizzazione potrebbe visualizzare il suo contenuto in una posizione dello schermo imprevista quando viene eseguito in iOS 7.

Per regolare il modo in cui un controller di visualizzazione espone le sue visualizzazioni, UIViewController fornisce le seguenti proprietà:

  • edgesForExtendedLayout

La edgesForExtendedLayoutproprietà utilizza il UIRectEdgetipo, che specifica ciascuno dei quattro bordi di un rettangolo, oltre a specificare nessuno e tutti. Utilizzare edgesForExtendedLayoutper specificare quali bordi di una vista devono essere estesi, indipendentemente dalla traslucenza della barra. Per impostazione predefinita, il valore di questa proprietà è UIRectEdgeAll.

  • extendedLayoutIncludesOpaqueBars

Se il tuo progetto utilizza barre opache, perfeziona edgesForExtendedLayoutanche impostando la extendedLayoutIncludesOpaqueBarsproprietà su NO . (Il valore predefinito extendedLayoutIncludesOpaqueBarsè NO .)

  • automaticallyAdjustsScrollViewInsets

Se non desideri che gli inserti del contenuto di una vista di scorrimento vengano regolati automaticamente, imposta automaticallyAdjustsScrollViewInsetssu NO . (Il valore predefinito automaticallyAdjustsScrollViewInsetsè .)

  • topLayoutGuide, bottomLayoutGuide

Le proprietà topLayoutGuidee bottomLayoutGuideindicano la posizione dei bordi della barra superiore o inferiore nella vista di un controller di vista. Se le barre devono sovrapporsi alla parte superiore o inferiore di una vista, è possibile utilizzare Interface Builder per posizionare la vista rispetto alla barra creando vincoli nella parte inferiore topLayoutGuideo nella parte superiore di bottomLayoutGuide. (Se nessuna barra deve sovrapporsi alla vista, la parte inferiore di topLayoutGuideè uguale alla parte superiore della vista e la parte superiore bottomLayoutGuideè uguale alla parte inferiore della vista.) Entrambe le proprietà vengono create pigramente quando richiesto.

Si prega di fare riferimento, apple doc


2
Non verrà compilato sotto iOS6. Penso che dovrebbe essere scritto come performelector ...
Shmidt

8
Sì, è per questo che ho incluso il controllo di selezione con if condition, if ([self respondsToSelector: @selector (edgeForExtendedLayout)])
Nandha

19
Questo non funzionerebbe se non ho una barra di navigazione. In tal caso, il mio punto di vista si estende dietro la barra di stato ...
Van Du Tran,

4
Ho lo stesso problema di @VanDuTran. edgeForExtendedLayout non aiuta se la barra di navigazione è nascosta.
fishinear

6
funziona ma ... non c'è più effetto traslucido ... come possiamo preservare anche l'effetto traslucido ...
Dipu Rajak

110

Non devi calcolare fino a che punto spostare tutto verso il basso, per questo c'è una build in proprietà. In Interface Builder, evidenzia il tuo controller di visualizzazione, quindi vai alla finestra di ispezione degli attributi. Qui vedrai alcune caselle di controllo accanto alle parole "Estendi bordi". Come puoi vedere, nella prima schermata, la selezione predefinita è che i contenuti vengano visualizzati sotto le barre superiore e inferiore, ma non sotto le barre opache, motivo per cui l'impostazione dello stile della barra su non traslucido ha funzionato per te.

Come puoi vedere nella prima schermata, ci sono due elementi dell'interfaccia utente nascosti sotto la barra di navigazione. (Ho abilitato i wireframe in IB per illustrare questo) Questi elementi, un UIButton e un UISegmentedControl hanno entrambi l'origine "y" impostata su zero e il controller di visualizzazione è impostato per consentire il contenuto sotto la barra superiore.

inserisci qui la descrizione dell'immagine

Questo secondo screenshot mostra cosa succede quando si deseleziona la casella di controllo "Sotto le barre superiori". Come puoi vedere, la vista dei controller di visualizzazione è stata spostata correttamente verso il basso in modo che la sua origine y si trovi proprio sotto la barra di navigazione.

inserisci qui la descrizione dell'immagine

Questo può essere realizzato anche a livello di programmazione attraverso l'uso di -[UIViewController edgesForExtendedLayout]. Ecco un collegamento al riferimento di classe per edgeForExtendedLayout e per UIRectEdge

[self setEdgesForExtendedLayout:UIRectEdgeNone];

15
Come posso fare lo stesso solo per la visualizzazione in un .xib?
bobici,

2
Ho aggiunto un'etichetta alla vista e ho seguito le tue istruzioni, ma questo non funziona per me
RMRAHUL

5
@bobics La risposta alla domanda XIB è "Non puoi". Non attraverso IB comunque. Presentare un radar e sperare che Apple alla fine lo risolva.
Memmons

Grazie @ 0x7fffffff, queste erano solo le informazioni che stavo cercando ed è stato molto utile.
campo

33

Ho creato la mia vista a livello di codice e questo ha funzionato per me:

- (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;
    }
}

Sorgente (nella sezione topLayoutGuide in fondo a pag.39).


Finalmente ho trovato una risposta che funziona davvero per questo. Buon lavoro!
StuartM,

1
Per risolvere il problema per cui la vista del controller di visualizzazione viene visualizzata sotto la barra di stato quando la barra di navigazione è nascosta, questo è il codice che esegue lo snap della vista sotto la barra di stato.
MiKL

Nota: questo sposterà la parte inferiore della vista dallo schermo.
Memmons

1
Inoltre, a meno che tu non stia costruendo solo per iOS7, il codice sopra genererà un errore - topLayoutGuideè solo iOS7.
Memmons

1
Si noti inoltre che quando la vista principale è un UITableView, viewDidLayoutSubviews verrà chiamato su ogni scorrimento. Il tuo UITableView verrà ridimensionato fino a quando la sua altezza è di 15 px. Aggiungi un flag per eseguire questo codice una sola volta. ;)
Thomas Johannesmeyer,

30

Soluzione Swift 3 / Swift 4 che funziona anche con file NIB / XIB in iOS 10+:

override func viewDidLoad() {
    super.viewDidLoad()

    edgesForExtendedLayout = []
}

Questo è ciò che mi ha aiutato ... così semplice. Grazie :-)
Hernan Arber,

Grazie è davvero utile
Muhammad Ahmed Baig,

Questa è la soluzione migliore per 10.x Swift 3+ IMO
shokaveli,

10

Se vuoi che la vista abbia la barra di navigazione traslucida (che è piuttosto carina) devi impostare un contentInset o simile.

Ecco come lo faccio:

// 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);
}

3
perché non puoi confrontarlo direttamente con 7.0
Leena,

1
lol capisco: il controllo con una versione specifica con aggiunta minore è meno robusto. Ma stai verificando se il valore è PIÙ GRANDE o uguale a così rispetto a 7.0 farebbe bene qui;)
EeKay

1
@leena - Queste sono le funzionalità in 7.xe successive - quindi controllo se la versione è 7 o successiva e salta le revisioni minori nel controllo.
Magnus,

2
Ho avuto un problema con il mio tableView che veniva visualizzato dietro la mia Tabbar. Il che ha reso l'ultima riga del mio tavolo mai scorrere sopra la barra delle schede. L'ho risolto in questo modo: myTableView.contentInset = UIEdgeInsetsMake (0, 0,0, TabbarHeight, 0)
James Laurenstin

contentInsetè di proprietà di UIScrollView. E se la mia vista principale non fosse una sottoclasse di UIScrollView. Quindi come risolverei il problema di sovrapposizione?
Pwner

9

edgesForExtendedLayoutfa il trucco per iOS 7. Tuttavia, se si sviluppa l'app su iOS 7 SDK e la si distribuisce in iOS 6, la barra di navigazione appare traslucida e le viste vanno sotto di essa. Quindi, per risolverlo sia per iOS 7 che per iOS 6, fai questo:

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

9

Nel file plist delle tue app aggiungi una riga, chiamala "Visualizza l'aspetto della barra di stato basata sul controller" e impostala su NO .


7

Il trucco più semplice è aprire il file NIB ed eseguire questi due semplici passaggi:

  1. Attivalo e impostalo su quello che preferisci:

Inserisci qui la descrizione dell'immagine

  1. Seleziona quelle UIView / UIIMageView / / che desideri spostare verso il basso. Nel mio caso solo il logo era sovrapposto e ho impostato il delta su +15; (OPPURE -15 se hai scelto iOS 7 al passaggio 1)

Inserisci qui la descrizione dell'immagine

E il risultato :

Prima Dopo


6
Funziona, ma sembra una soluzione difficile da mantenere. Sarebbe meglio risolvere il problema invece di correggerlo.
NL,

sarebbe meglio farlo a livello di codice per tutte le sottoview della vista perché non funziona se applicato alla vista principale
wildmonkey,

5

Soluzione rapida:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None
}

4
Questo è adesso edgeForExtendedLayout = []
Leon il

1
Poiché questa è una risposta pubblica, non dovremmo dimenticare di chiamare:super.viewWillAppear(animated)
prodos,

4

Vorrei espandere la risposta di Stunner e aggiungere un if dichiarazione per verificare se si tratta di iOS-7, perché quando l'ho provato su iOS 6 la mia app andava in crash.

L'aggiunta sarebbe aggiungere:

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

Quindi suggerirei di aggiungere questo metodo al tuo MyViewControler.mfile:

- (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;
    }
}

4

Swift 3

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

3

Ho uno scenario in cui utilizzo BannerViewController scritto da Apple per visualizzare i miei annunci e uno ScrollViewController incorporato in BannerViewController.

Per impedire alla barra di navigazione di nascondere il mio contenuto, ho dovuto apportare due modifiche.

1) Modifica BannerViewController.m

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

2) Modifica il mio ScrollViewContoller

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

Ora gli annunci vengono visualizzati correttamente nella parte inferiore della vista invece di essere coperti dalla barra di navigazione e il contenuto in alto non viene tagliato.


2

apparirà il seguente codice in vista.

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
 }

Questa è l'unica cosa che ha funzionato nelle mie circostanze.
goobliata,


2

Swift 4.2 - Xcode 10.0 - iOS 12.0:

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

1

Per me, la soluzione più semplice è aggiungere due chiavi nel plist

inserisci qui la descrizione dell'immagine


+1, avevo la "Barra di stato inizialmente nascosta" = SÌ, ma quando ho aggiunto "Visualizza l'aspetto della barra di stato basata sul controller" = NO mi sono sbarazzato della barra di stato.
Jonas Byström,

1

Aggiungi la chiave "Visualizza l'aspetto della barra di stato basata sul controller" dall'elenco a discesa come riga in info.plist. Qualcosa come questo:

Inserisci qui la descrizione dell'immagine


interesting.it mi ha aiutato con i miei progetti cocos2d. Come attivare questa opzione, posso vedere che la barra di stato superiore è completamente scomparsa o visualizzata.
Kursat Turkay,

1

Ho avuto lo stesso problema con la mia app da iPad (armv7, armv7s, amr64) solo presentando un altro UIViewController e dopo averli scartati passa la barra di navigazione sotto la barra di stato ... Passo molto tempo a trovare una soluzione per questo. Sto usando lo storyboard e in InterfaceBuilder per UIViewController, il che rende terribile impostare Presentazione da FullScreen -> Contesto corrente e risolve questo problema. Funziona nella mia app solo per iPad => iOS8.0 (test con iOS8.1) e per iPad con iOS 7.1 non funziona !!vedi screenshot


Nel mio caso, la mia vista principale si sovrapponeva alla mia barra delle schede e non avevo idea del perché. Si scopre che è stato controllato Estendi bordi> Sotto le barre inferiori. È stato davvero difficile notarlo perché lo sfondo della mia app era bianco e ha generato solo un'opacità di livello sulla mia barra delle schede. Grazie!
Jesus Rodriguez,

0

Passaggi per Nascondi la barra di stato in iOS 7:

1. Vai al file info.plist dell'applicazione.

2.E impostare, Visualizza l'aspetto della barra di stato basata sul controller: NO booleano

Spero di aver risolto il problema della barra di stato .....


0

Nel mio caso avere loadView () interrotto
questo codice: self.edgesForExtendedLayout = UIRectEdgeNone

ma dopo aver eliminato loadView () tutto ha funzionato bene

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.