Pasek stanu iOS 7 z powrotem do domyślnego stylu iOS 6 w aplikacji iPhone?

292

W iOS 7 UIStatusBarzostał zaprojektowany w taki sposób, że łączy się z takim widokiem:

GUI zaprojektowany przez Tinę Tavčar (GUI zaprojektowany przez Tinę Tavčar )

  • Jest fajny, ale nieco zepsuje widok, gdy masz coś w górnej części widoku, i nakłada się na pasek stanu.

  • Czy istnieje proste rozwiązanie (takie jak ustawienie właściwości w info.plist), które może zmienić sposób, w jaki działa [nie nakładając się], z powrotem na to, jak to jest w iOS6?

  • Wiem, że bardziej prostym rozwiązaniem jest posiadanie self.view.center.x+ 20 punktów za każdy kontroler widoku, ale ich zmiana spowoduje zepsucie innych wymiarów (inne self.view.center.xmogą powodować problemy z niestandardowymi sekwencjami itp.) I nagle zamienia się w żmudną pracę, która jest najlepiej tego unikać.

  • Będę naprawdę zadowolony, jeśli ktoś może zapewnić mi jedno-liniowe rozwiązanie tego problemu.

PS Wiem, że mogę ukryć pasek stanu, wykonując takie czynności, jak posiadanie

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

W didFinishLaunchingWithOptionsmetodzie, ale jest to obejście, skrót pozwalający uniknąć problemu, więc nie uważam tego za prawdziwe rozwiązanie.

吖 奇 说 - 何魏奇 Archy Will He
źródło
6
Niestety czarne pasy statusu zostały wycofane w
iOS
Zgodzę się z @GangstaGraham. Te kolory są po prostu piękne ! Aby odpowiedzieć na twoje pytanie, obawiam się, że nie możesz. Powodem, dla którego pasek stanu jest tak zaprojektowany, jest to, że przezroczystość jest nową rzeczą dla systemu iOS i ma na celu nadanie aplikacji „głębi”, mówiąc, że jest nad czymś, więc pod spodem jest coś.
Cole Johnson
Czy próbowałeś ustawić preferowaneStatusBarStyle na UIStatusBarDefault? Kasa Dokumentacja UIViewController dla iOS 7
theaob
1
Posiadanie UIStatusBarDefaultpaska stanu powoduje, że jego zawartość jest tylko czarna. Nie zmieni sposobu, w jaki działa z powrotem na system iOS6.
吖 奇 说 - 何魏奇 Archy Will He
2
Masz z tym szczęście? Uwielbiam iOS7, ale to doprowadza mnie do szału!
Mihai Fratu,

Odpowiedzi:

449

Jest to cross-posty z posta na blogu, który napisałem , ale tutaj jest pełne podsumowanie pasków stanu, pasków nawigacji i kontrolerów widoku kontenerów w iOS 7:

  1. Nie ma sposobu na zachowanie układu paska stanu w stylu iOS 6. Pasek stanu zawsze będzie nakładał się na twoją aplikację na iOS 7

  2. Nie należy mylić wyglądu paska stanu z układem paska stanu. Wygląd (jasny lub domyślny) nie ma wpływu na układ paska stanu (ramka / wysokość / nakładanie się). Należy również pamiętać, że pasek stanu systemu nie ma już żadnego koloru tła. Gdy interfejs API odwołuje się do UIStatusBarStyleLightContent, oznacza to biały tekst na czystym tle. UIStatusBarStyleDefault to czarny tekst na czystym tle.

  3. Wygląd paska stanu jest kontrolowany wzdłuż jednej z dwóch wzajemnie wykluczających się ścieżek bazowych: możesz albo ustawić je programowo w tradycyjny sposób, albo UIKit zaktualizuje dla ciebie wygląd na podstawie niektórych nowych właściwości UIViewController. Ta ostatnia opcja jest domyślnie włączona. Sprawdź wartość plist aplikacji dla „Wygląd paska stanu opartego na ViewController”, aby zobaczyć, którego używasz. Jeśli ustawisz tę wartość na TAK, każdy kontroler widoku najwyższego poziomu w Twojej aplikacji (inny niż standardowy kontroler widoku kontenera UIKit) musi zastąpić preferowanyStatusBarStyle, zwracając styl domyślny lub lekki. Jeśli edytujesz wartość plist na NIE, możesz zarządzać wyglądem paska stanu przy użyciu znanych metod UIApplication.

  4. UINavigationController zmieni wysokość swojego paska UINavigationBar na 44 punkty lub 64 punkty, w zależności od dość dziwnego i nieudokumentowanego zestawu ograniczeń. Jeśli UINavigationController wykryje, że górna część ramki jego widoku jest wizualnie przylegająca do górnej części swojego interfejsu UIWindow, wówczas rysuje pasek nawigacji o wysokości 64 punktów. Jeśli wierzchołek jego widoku nie sąsiaduje z wierzchołkiem UIWindow (nawet jeśli jest wyłączony tylko o jeden punkt), wówczas rysuje pasek nawigacji w „tradycyjny” sposób z wysokością 44 punktów. Ta logika jest wykonywana przez UINavigationController, nawet jeśli w hierarchii kontrolera widoku aplikacji znajduje się kilka dzieci. Nie ma sposobu, aby temu zapobiec.

  5. Jeśli podasz niestandardowy obraz tła paska nawigacji, który ma tylko 44 punkty (88 pikseli), a granice widoku UINavigationController są zgodne z granicami UIWindow (jak omówiono w punkcie 4), UINavigationController narysuje obraz w ramce (0,20,320 , 44), pozostawiając 20 punktów nieprzezroczystej czarnej przestrzeni nad niestandardowym obrazem. To może pomylić Cię z myśleniem, że jesteś sprytnym programistą, który ominął zasadę nr 1, ale się mylisz. Pasek nawigacyjny ma nadal 64 punkty wysokości. Osadzenie UINavigationController w hierarchii widoków typu „przesuń, aby odsłonić” wyraźnie to wyjaśnia.

  6. Uważaj na myląco nazwaną edgeForExtendedLayout właściwość UIViewController. Dostosowywanie krawędziForExtendedLayout w większości przypadków nic nie robi. Jedynym sposobem, w jaki UIKit używa tej właściwości, jest dodanie kontrolera widoku do kontrolera UINavigationController, a następnie kontroler UINavigationController korzysta z edgeForExtendedLayout w celu ustalenia, czy jego kontrolka widoku potomnego powinna być widoczna pod paskiem nawigacji / obszarem paska stanu. Ustawienie EdgeForExtendedLayout na samym UINavigationController nie robi nic, aby zmienić, czy UINavigationController ma obszar paska nawigacji o wysokości 44 lub 64 punktów. Ta logika znajduje się w punkcie 4. Podobna logika układu ma zastosowanie do dolnej części widoku, gdy używany jest pasek narzędzi lub UITabBarController.

  7. Jeśli wszystko, co próbujesz zrobić, to zapobiec temu, aby niestandardowy kontroler widoku potomnego nie zasłaniał paska nawigacyjnego wewnątrz UINavigationController, a następnie ustaw edgeForExtendedLayout na UIRectEdgeNone (lub przynajmniej maskę wykluczającą UIRectEdgeTop). Ustaw tę wartość jak najwcześniej w cyklu życia kontrolera widoku.

  8. UINavigationController i UITabBarController również spróbują uzupełnić contentInsets widoków tabel i widoków kolekcji w swojej hierarchii widoków podrzędnych. Robi to w sposób podobny do logiki paska stanu z punktu 4. Istnieje programowy sposób, aby temu zapobiec, ustawiając automatycznieAdjustsScrollViewInsets na NIE dla widoków tabeli i widoków kolekcji (domyślnie TAK). To spowodowało poważne problemy dla Whisper i Riposte, ponieważ używamy dopasowań contentInset do kontrolowania układu widoków tabeli w odpowiedzi na ruchy paska narzędzi i klawiatury.

  9. Powtórzmy: nie ma możliwości powrotu do logiki układu paska stanu w stylu iOS 6. Aby to przybliżyć, musisz przenieść wszystkie kontrolery widoku swojej aplikacji do widoku kontenera, który jest przesunięty o 20 punktów od góry ekranu, pozostawiając celowo czarny widok za paskiem stanu, aby symulować stary wygląd. Jest to metoda, którą ostatecznie wykorzystaliśmy w Riposte i Whisper.

  10. Apple bardzo mocno naciska, aby upewnić się, że nie spróbujesz zrobić # 9. Chcą, abyśmy przeprojektowali wszystkie nasze aplikacje tak, aby pokrywały się pasek stanu. Istnieje jednak wiele przekonywujących argumentów, zarówno z uwagi na doświadczenie użytkownika, jak i względy techniczne, dlaczego nie zawsze jest to dobry pomysł. Powinieneś robić to, co najlepsze dla swoich użytkowników, a nie tylko podążać za kaprysem platformy.

jaredsinclair
źródło
35
Chciałem tylko dodać, że możesz dodać ograniczenie do wszystkiego, co znajduje się u góry widoku, aby dołączyć je do górnego przewodnika układu - pozostawi puste miejsce za paskiem stanu (który możesz wypełnić dowolnym kolorem) ale pozwoli również automatycznie dopasować widok do prawidłowej pozycji w iOS 6. W ten sposób nie musisz ręcznie dostosowywać pozycji swoich widoków w kodzie.
BreadicalMD
4
To wspaniałe rozwiązanie. Obnażyłeś moją ignorancję w AutoLayout. Lepiej weź to.
jaredsinclair
1
Jeśli umieścisz górną przestrzeń obiektu pod krawędzią górnej prowadnicy układu, możesz użyć kontroli ograniczenia, aby dodać ograniczenie odległości w pionie do najbliższego sąsiada, który będzie teraz najwyższym przewodnikiem układu. Alternatywnie możesz użyć kombinacji klawiszy Ctrl + kliknięcie z obiektu do górnego przewodnika po układzie, aby jawnie dodać ograniczenie pionowego odstępu.
BreadicalMD
2
@BreadicalMD Jedna część, której nie rozumiem, to to, że -topLayoutGuide nie jest dostępny na iOS 6, więc czy to oznacza, że ​​musisz używać różnych ograniczeń automatycznego układu na iOS 7 i 6?
Jeremy
1
Świetna odpowiedź ... Ale mam jedną wątpliwość 1) UINavigationController zmieniający część wysokości. Proszę wyjaśnić to nieco więcej. dzięki
użytkownik1010819,
122

Aktualizacje 19 września 2013:

naprawiono błędy skalowania poprzez dodanie self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);

poprawione literówki w NSNotificationCenterzestawieniu


Aktualizacje 12 września 2013:

poprawione UIViewControllerBasedStatusBarAppearancedoNO

dodano rozwiązanie dla aplikacji z obracaniem ekranu

dodano podejście do zmiany koloru tła paska stanu.


Najwyraźniej nie ma możliwości przywrócenia paska stanu systemu iOS7 z powrotem do sposobu działania w systemie iOS6.

Jednak zawsze możemy napisać niektóre kody i zmienić pasek stanu w iOS6, a to jest najkrótszy sposób, jaki mogę wymyślić:

  1. Ustaw UIViewControllerBasedStatusBarAppearancesię NOw info.plist(Aby zrezygnować z konieczności widok kontrolerów dostosować status bar styl, dzięki czemu możemy ustawić styl paska stanu przy użyciu metody UIApplicationstatusBarStyle).

  2. W AppDelegate application:didFinishLaunchingWithOptionszadzwoń

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        [application setStatusBarStyle:UIStatusBarStyleLightContent];
        self.window.clipsToBounds =YES;
        self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
    
        //Added on 19th Sep 2013
        self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
    }
    return YES;
    


w celu:

  1. Sprawdź, czy to iOS 7.

  2. Ustaw zawartość paska stanu na białą, w przeciwieństwie do UIStatusBarStyleDefault.

  3. Unikaj wyświetlania widoków podrzędnych, których ramki wykraczają poza widoczne granice, aby się nie pokazywały (dla widoków animowanych do widoku głównego od góry).

  4. Stwórz złudzenie, że pasek stanu zajmuje miejsce, podobnie jak w iOS 6, przesuwając i zmieniając ramkę okna aplikacji.


W przypadku aplikacji z obracaniem ekranu

użyj NSNotificationCenter do wykrywania zmian orientacji poprzez dodanie

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidChangeStatusBarOrientation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];

w if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)i utworzyć nową metodę w AppDelegate:

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
    int a = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
    int w = [[UIScreen mainScreen] bounds].size.width;
    int h = [[UIScreen mainScreen] bounds].size.height;
    switch(a){
        case 4:
            self.window.frame =  CGRectMake(0,20,w,h);
            break;
        case 3:
            self.window.frame =  CGRectMake(-20,0,w-20,h+20);
            break;
        case 2:
            self.window.frame =  CGRectMake(0,-20,w,h);
            break;
        case 1:
           self.window.frame =  CGRectMake(20,0,w-20,h+20);
    }
}

Tak, gdy zmiana orientacji spowoduje wyzwolenie instrukcji przełączania, aby wykryć orientację ekranu aplikacji (Pionowo, Do góry nogami, Poziomo w lewo lub Poziomo w prawo) i odpowiednio zmienić ramkę okna aplikacji, aby stworzyć iluzję paska stanu iOS 6.


Aby zmienić kolor tła paska stanu:

Dodaj

 @property (retain, nonatomic) UIWindow *background;

w, AppDelegate.haby zrobić backgroundwłasność w swojej klasie i zapobiec cofnięciu przydziału przez ARC. (Nie musisz tego robić, jeśli nie używasz ARC.)

Następnie wystarczy utworzyć UIWindow w if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1):

background = [[UIWindow alloc] initWithFrame: CGRectMake(0, 0, self.window.frame.size.width, 20)];
background.backgroundColor =[UIColor redColor];
[background setHidden:NO];

Nie zapomnij @synthesize background;po @implementation AppDelegate!

吖 奇 说 - 何魏奇 Archy Will He
źródło
3
To się psuje podczas rotacji. tylko jeden na jednego
Jesse Naugher
2
@JesseNaugher Polecam programowo zmodyfikować Ograniczenie pionowego odstępu od 0 do 20. Będzie działał na rotacji.
ekspert
2
Masz pomysł, jak możemy uniknąć powiększenia paska nawigacji o 20 pikseli? To rozwiązanie jest dla mnie w porządku, ale mój pasek nawigacji jest o 20 pikseli za wysoki.
simonbs
4
@ArchyHolt: Twoje proste rozwiązanie działa dla mnie, z wyjątkiem sytuacji, gdy przedstawiam kontroler widoku modalnego. Po zamknięciu kontrolera widoku modalnego pozostały widok znajduje się teraz pod paskiem stanu. Powtórzyłem to w świeżym projekcie próbki, aby upewnić się, że nie dzieje się nic więcej funky. Myślę, że może bardziej przydatne może być twoje bardziej zaawansowane rozwiązanie, ale nie jestem pewien, jakie powiadomienie wejdzie w grę. Jakieś pomysły?
markdorison
4
Widok resetuje się po odrzuceniu modalnego kontrolera widoku. :(
KarenAnne,
41

AKTUALIZACJA (NOWE ROZWIĄZANIE)

Ta aktualizacja jest najlepszym rozwiązaniem problemu paska nawigacji w systemie iOS 7. Możesz ustawić przykład koloru paska nawigacji: FakeNavBar.backgroundColor = [UIColor redColor];

Uwaga: Jeśli używasz domyślnego kontrolera nawigacji, użyj starego rozwiązania.

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if(NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0)
    {
        UIView *FakeNavBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
        FakeNavBar.backgroundColor = [UIColor whiteColor];

        float navBarHeight = 20.0;
        for (UIView *subView in self.window.subviews) {

            if ([subView isKindOfClass:[UIScrollView class]]) {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height - navBarHeight);
            } else {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height);
            }
        }
        [self.window addSubview:FakeNavBar];
    }

    return YES;

}

STARE ROZWIĄZANIE - JEŚLI używasz poprzedniego kodu, zignoruj ​​następujący Kod i Obraz

To jest stara wersja paska nawigacji systemu iOS 7.

Rozwiązałem problem z następującym kodem. Służy do dodawania paska stanu. didFinishLaunchingWithOptions

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    UIView *addStatusBar = [[UIView alloc] init];
    addStatusBar.frame = CGRectMake(0, 0, 320, 20);
    addStatusBar.backgroundColor = [UIColor colorWithRed:0.973 green:0.973 blue:0.973 alpha:1]; //change this to match your navigation bar
    [self.window.rootViewController.view addSubview:addStatusBar];
}

W przypadku konstruktora interfejsów jest to możliwe po otwarciu w systemie iOS 6; zaczyna się od 0 pikseli.

Uwaga: delty iOS 6/7 pojawiają się tylko po odznaczeniu opcji „Użyj automatycznego układania” dla kontrolera widoku w „Inspektorze plików” (ikona po lewej stronie) w okienku szczegółów.

Wpisz opis zdjęcia tutaj

İbrahim Özbölük
źródło
6
Zrobiłeś mi dzień i weź +1 za pomoc!
Niru Mukund Shah,
5
Uwaga: delty iOS 6/7 pojawiają się tylko po odznaczeniu opcji „Użyj automatycznego układania” dla kontrolera widoku w „Inspektorze plików” (ikona po lewej stronie) w okienku szczegółów.
Matt
1
Wielkie dzięki! Zaoszczędziłeś mi dużo kłopotów!
neowinston
2
Kto powiedział, że układ paska stanu w stylu iOS 6 nie może być utrzymany, Możesz to zrobić w sposób @ TacettinÖzbölük ... dzięki za to rozwiązanie.
Vizllx,
1
niezłe! również, aby zauważyć, że Apple woli teraz: if (NSFoundationVersionNumber> = NSFoundationVersionNumber_iOS_6_1) {}
Joel Balmer
26

ROZWIĄZANIE :

Ustaw go w kontroler widoku lub w kontroler rootview, zastępując metodę:

-(BOOL) prefersStatusBarHidden
    {
        return YES;
    }
Dave
źródło
Niezłe rozwiązanie. Całkowicie usuń pasek. Może nie być idealny dla UX przez cały czas, ale wykonalny.
Farhan Hafeez
Poprostu super. Pracował dla mnie bezbłędnie.
madLokesh
Scenariusz: po ponownym przełączeniu się na UIVIew po odtworzeniu wideo w trybie pełnoekranowym u dołu pojawia się czarny pasek, który ma rozmiar paska stanu, chociaż już korzystałem z paska stanu. Całkowicie usunąłem pasek stanu i teraz problem został rozwiązany.
madLokesh
Udało mi się tylko przy użyciu tej metody
user2277872
17

Oto inne podejście do projektów, które szeroko wykorzystują Storyboard:

CEL:

Celem tego podejścia jest odtworzenie tego samego stylu paska stanu w systemie iOS7, jak w systemie iOS6 (patrz tytuł pytania „Pasek stanu systemu iOS 7 Z powrotem do stylu systemu iOS 6”).

PODSUMOWANIE:

Aby to osiągnąć, wykorzystujemy Storyboard w jak największym stopniu, przesuwając w dół elementy interfejsu, które nakładają się na pasek stanu (w iOS 7), przy użyciu delt do przywrócenia zmiany układu w dół dla iOS 6.1 lub wcześniejszej. Wynikowa dodatkowa przestrzeń w iOS 7 jest następnie zajmowana przez UIView z ustawionym tłem backgroundColor na wybrany przez nas kolor. Ten ostatni można utworzyć w kodzie lub przy użyciu Storyboard (patrz poniżej ALTERNATYWY)

ZAŁOŻENIA:

Aby uzyskać pożądany rezultat, wykonując poniższe kroki, zakłada się, że View controller-based status bar appearancejest ustawiony na NIE i że Status bar stylealbo jest ustawiony na „Przezroczysty czarny styl (alfa 0,5)” lub „Nieprzezroczysty czarny styl”. Oba ustawienia można znaleźć / lub dodać w części „Informacje” w ustawieniach projektu.

KROKI:

  • Dodaj widok podrzędny do UIWindow, aby służył jako tło paska stanu. Aby to osiągnąć, dodaj następujące elementy do aplikacji AppDelegate application: didFinishLaunchingWithOptions:pomakeKeyAndVisible

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        UIView *statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourAppsUIWindow.frame.size.width, 20)];
        statusBarBackgroundView.backgroundColor = [UIColor blackColor];
        [yourAppsUIWindow addSubview:statusBarBackgroundView];
    }
    
  • Ponieważ programowo dodałeś tło TYLKO dla iOS 7, będziesz musiał odpowiednio dostosować układ elementów interfejsu, które nakładają się na pasek stanu, jednocześnie zachowując ich układ dla iOS6. Aby to osiągnąć, wykonaj następujące czynności:

    • Upewnij się, że Use Autolayoutnie jest zaznaczone dla twojej Storyboard (dzieje się tak, ponieważ inaczej „iOS 6/7 Deltas” nie jest wyświetlany w Inspektorze rozmiarów). Aby to zrobić:
      • wybierz plik Storyboard
      • pokaż Narzędzia
      • wybierz „Pokaż inspektora plików”
      • W sekcji „Dokument konstruktora interfejsów” usuń zaznaczenie opcji „Użyj automatycznego układania”
    • Opcjonalnie, aby pomóc Ci monitorować zmiany układu zarówno w systemie iOS 7, jak i 6 podczas ich stosowania, wybierz „Asystenta edytora”, wybierz „Podgląd” i „iOS 6.1 lub wcześniejszy”: wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj
    • Teraz wybierz element interfejsu, który chcesz dostosować, aby nie był już nakładany na pasek stanu
    • Wybierz „Pokaż inspektor rozmiaru” w kolumnie Narzędzia
    • Zmień położenie elementu interfejsu użytkownika wzdłuż osi Y o tę samą wartość, co wysokość paska stanu bg: wprowadź opis zdjęcia tutaj
    • I zmień wartość delty iOS6 / 7 dla Y o tę samą NEGATYWNĄ wysokość co wysokość paska stanu bg (zwróć uwagę na zmianę w podglądzie iOS 6, jeśli go używasz): wprowadź opis zdjęcia tutaj

ALTERNATYWY:

Aby dodać jeszcze mniej kodu w projektach obfitujących w scenorysy i mieć autorotację tła paska stanu, zamiast programowo dodawać tło paska stanu, możesz dodać kolorowy widok do każdego kontrolera widoku, który znajduje się na samej górze głównego widoku kontrolera widoku. Następnie zmieniłbyś różnicę wysokości tego nowego widoku na tę samą ujemną wartość, co wysokość twojego widoku (aby zniknął pod iOS 6).

Minusem tej alternatywy (chociaż może być nieistotna, biorąc pod uwagę zgodność autorotate) jest fakt, że ten dodatkowy widok nie jest od razu widoczny, jeśli przeglądasz Storyboard na iOS 6. Gdybyś spojrzał na „ Zarys dokumentu ”w serii ujęć.

sts2055
źródło
12

Jeśli nie chcesz, aby kontrolery widoku nakładały się na pasek stanu (i paski nawigacji), odznacz pole „Rozszerz krawędzie pod górnymi pasami” w Konstruktorze interfejsów w Xcode 5.

Usuń zaznaczenie opcji Rozszerz krawędzie pod górnymi pasami

nvrtd frst
źródło
7
Jest to możliwe tylko wtedy, gdy używasz scenorysu
Cœur
3
Działa tylko z kontenerami vcs, takimi jak kontroler nawigacji lub kontroler paska kart
Andrea
2
EdgeForExtendedLayout jest używany tylko przez kontrolery widoku kontenera (takie jak UINavigationController) w celu ustalenia, czy widoki jego dziecka powinny nakładać się na chrom rodzica. Ustawienie tej właściwości w kontrolerze widoku głównego dla UIWindow nic nie robi. Zobacz moją odpowiedź powyżej: stackoverflow.com/questions/18294872/…
jaredsinclair
Jak to zrobić dla UITabBarController @Andrea? Dzięki.
KarenAnne,
@KarenAnne Zależy, jeśli robisz programowo lub za pomocą scenariuszy. Programowo musisz tylko ustawić właściwość edgeForExtent na to, co lubisz w kontrolerze widoku, który wyświetlasz w UITabBarViewController, ale aby nie mieć problemu z paskiem stanu, musisz załadować kontroler uinavigation wewnątrz th UITabbarController. Sprawdź tutaj. developer.apple.com/library/ios/documentation/UserExperience/...
Andrea
11

Firma Apple wydała Techniczne pytania i odpowiedzi QA1797: Zapobieganie zasłanianiu paska stanu . Działa dobrze dla wersji iOS 6 i iOS 7.

Igor
źródło
5
Apple zakłada, że ​​wszyscy używają automatycznego układu. Auto-układ był okropny w Xcode 4, a Xcode 5 został właśnie wydany, więc jest to wątpliwe założenie.
Glenn Maynard
1
Ale w perspektywie jest to lepsze rozwiązanie niż zmiana rozmiaru ramki okna głównego lub paska stanu.
Igor
O ile mi wiadomo, rozwiązanie Apple nie działa, jeśli rootViewController jest splitViewController.
Vern Jensen
8

Obejrzałem wiele, wiele i wiele samouczków, aby rozwiązać ten cholerny problem. Ale żaden z nich nie działa! Oto moje rozwiązanie i działa dla mnie:

if( [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f ) {
    float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
    for( UIView *v in [self.view subviews] ) {
        CGRect rect = v.frame;
        rect.origin.y += statusBarHeight;
        v.frame = rect;
    }
}

Logika jest prosta. Przesuwam wszystkie widoki dzieci na self.view za pomocą 20 pikseli. To wszystko. Następnie zrzut ekranu wyświetli się tak samo jak iOS 6. Nienawidzę paska stanu iOS7! ~ "~

pożar
źródło
2
gdzie powinienem to dodać? czy w aplikacji delegat został uruchomiony z opcjami?
mhmdshawqi
Kiedy to robię, pasek stanu zmienia kolor na biały
ropo
6

Mała alternatywa dla odpowiedzi Archy Holt, nieco prostsza:

za. Ustaw UIViewControllerBasedStatusBarAppearancena NOinfo.plist

b. W AppDelegate„s application:didFinishLaunchingWithOptions:, zadzwoń:

if ([[UIDevice currentDevice].systemVersion floatValue] < 7)
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
else
{
    // handling statusBar (iOS7)
    application.statusBarStyle = UIStatusBarStyleLightContent;
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    self.window.clipsToBounds = YES;

    // handling screen rotations for statusBar (iOS7)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

I dodaj metodę:

- (void)applicationDidChangeStatusBarOrientationNotification:(NSNotification *)notification
{
    // handling statusBar (iOS7)
    self.window.frame = [UIScreen mainScreen].applicationFrame;
}

Możesz również rozważyć podklasę, UIWindowaby UIApplicationDidChangeStatusBarOrientationNotificationsobie poradzić .

Cœur
źródło
masz problem z presentViewController: animated: complete:?
TĐỗng Đỗ
@ TùngĐỗ prawda, więc stworzyłem alternatywę, która działa lepiej: stackoverflow.com/questions/18294872/...
Cœur
5

Użyłem tego we wszystkich moich kontrolerach widoku, to proste. Dodaj te linie do wszystkich metod viewDidLoad:

- (void)viewDidLoad{
    //add this 2 lines:
    if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

    [super viewDidLoad];
}
IgniteCoders
źródło
1
Działało jak urok i było całkiem łatwe. W ruchu ruby, przed wezwaniem do superużytkowania: self.edgesForExtendedLayout = UIRectEdgeNone if responssToSelector („edgeForExtendedLayout”)
tehprofessor
4

Wypróbuj tę prostą metodę ....

Krok 1 : Aby zmienić na pojedynczyviewController

[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];

Krok 2 : Aby zmienić całą aplikację

info.plist
      ----> Status Bar Style
                  --->UIStatusBarStyle to UIStatusBarStyleBlackOpaque

Krok 3 : Dodaj to również viewWillAppeardo każdego, aby dostosować statusbarwysokośćiOS7

    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 7) {
        CGRect frame = [UIScreen mainScreen].bounds;
        frame.origin.y+=20.0;
        frame.size.height-= 20.0;
        self.view.frame = frame;
        [self.view layoutIfNeeded];
    }
Rajesh Loganathan
źródło
3

Osiągnąłem pasek stanu jak iOS 6 w iOS 7.

Ustaw UIViewControllerBasedStatusBarAppearance na NO w info.plist

Wprowadź ten kod w - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptionsmetodzie

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    [application setStatusBarStyle:UIStatusBarStyleLightContent];
    self.window.clipsToBounds =YES;
    self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height);

    //Added on 19th Sep 2013
    NSLog(@"%f",self.window.frame.size.height);
    self.window.bounds = CGRectMake(0,0, self.window.frame.size.width, self.window.frame.size.height);
}

Może przesuwać wszystkie twoje widoki o 20 pikseli. Aby to zrobić, użyj następującego kodu w -(void)viewDidAppear:(BOOL)animatedmetodzie

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    CGRect frame=self.view.frame;
    if (frame.size.height==[[NSUserDefaults standardUserDefaults] floatForKey:@"windowHeight"])
    {
        frame.size.height-=20;
    }
    self.view.frame=frame;
}

Musisz ustawić wartość windowHeight Userdefaults po alokacji okna w metodzie didFinishLauncing, takiej jak

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[[NSUserDefaults standardUserDefaults] setFloat:self.window.frame.size.height forKey:@"windowHeight"];
Kwiat pustyni
źródło
Lepszym rozwiązaniem jest heightustawienie paska UINavigationBar na 64 zamiast 44. Wówczas pasek rozszerzy się aż do szczytu, jak w aplikacjach Apple.
Aaron Brager
@AaronBrager Ale moim wymaganiem było pokazanie paska stanu w stylu iOS 6.
Desert Rose
Czy możesz dodać rozwiązanie dla orientacji poziomej iOS 7 ?. Robię to samo. ale nie działa w iOS 7 Landscape.
sathiamoorthy
@DesertRose THX! To działa dla mnie, ale odcina pasek uitabbar na dole. Mam aplikację opartą na kontrolerze paska kart z 3 widokami, z których 2 to kontrolery widoku tabeli.
marciokoko,
1
Póki nie obrócę urządzenia (moje urządzenie z iOS 7 to iPad), to doskonale je naprawia. Ale kiedy się obrócę, czarny pasek pozostaje dokładnie tam, gdzie jest, a „widok” (przepraszam, jeśli to zły termin techniczny, jestem facetem od PhoneGap / web) utrzymuje skurczoną wysokość - tyle że nie jest już wysokością, to jest szerokość. To rozwiązanie nie obsługuje rotacji, ale jest to najlepsza poprawka, jaką widziałem - jak można ją poprawić, obserwując obroty urządzenia? Dzięki!
tylerl
2

Jeśli używasz Konstruktora interfejsów, spróbuj tego:

W twoim pliku xib:

1) Wybierz widok główny, ustaw kolor tła na czarny (lub inny kolor, który ma być na pasku stanu)

2) Upewnij się, że tło jest niezależnym widokiem podrzędnym umieszczonym jako dziecko potomne najwyższego poziomu widoku kontrolera.
Przesuń tło, aby stać się bezpośrednim dzieckiem widoku kontrolera. Sprawdź panel automatycznej zmiany rozmiaru, aby upewnić się, że zablokowałeś wszystkie krawędzie ramki, aktywowałeś obie osie elastyczności, a jeśli jest to UIImageView, ustaw tryb zawartości na Skaluj, aby wypełnić. Programowo przekłada się to na contentMode ustawione na UIViewContentModeScaleToFill i ma ustawioną maskę automatycznego zmieniania rozmiaru na (UIViewAutoresizingF FlexibleWidth | UIViewAutoresizingFiętkiWysokość).

3) Teraz przenieś wszystko, co jest zablokowane do góry - o 20 punktów i ustaw deltę Y 6/7 na iOS na -20.
Wszystkie dzieci najwyższego poziomu, które są zablokowane w górnej ramce w panelu automatycznej zmiany rozmiaru, należy przesunąć o 20 punktów w dół i ustawić delta Y dla iOS 6/7 na -20. (Cmd zaznacz je wszystkie i kliknij strzałkę w dół 20 razy - czy jest lepszy sposób?)

4) Dostosuj wysokość delta iOS 6/7 wszystkich powyższych elementów o elastycznej wysokości. Każdy element, który był zablokowany na górze i na dole ramki i miał włączoną elastyczną wysokość w panelu automatycznego przesuwania, musi mieć również ustawioną wysokość delty iOS 6/7 na 20. Obejmuje to wspomniany wyżej widok tła. Może się to wydawać anty intuicyjne, ale ze względu na kolejność ich stosowania jest to konieczne. Najpierw ustawia się wysokość ramki (w zależności od urządzenia), następnie stosuje się delty, a na koniec stosuje się maski automatycznej zmiany rozmiaru na podstawie pozycji przesunięcia wszystkich ramek podrzędnych - przemyśl to chwilę, to będzie miało sens.

5) Wreszcie, elementy, które były zablokowane do dolnej ramki, ale nie do górnej ramki, nie potrzebują w ogóle delt.

To da ci identyczny pasek stanu w iOS7 i iOS6.

Z drugiej strony, jeśli chcesz stylizować iOS7 przy jednoczesnym zachowaniu zgodności z iOS6, ustaw wartości delta Y / wysokość delty na 0 dla widoku tła.

Aby zobaczyć więcej informacji o migracji do iOS7, przeczytaj cały post: http://uncompiled.blogspot.com/2013/09/legacy-compatible-offsets-in-ios7.html

thebman
źródło
Brak delty podczas korzystania z automatycznego układu
lostintranslation
2

Moim rozwiązaniem było dodanie UIViewwysokości 20 punktów w górnej części okna w systemie iOS 7. Następnie utworzyłem metodę w mojej klasie AppDelegate, aby pokazać / ukryć „stałe” tło paska stanu. W application:didFinishLaunchingWithOptions::

// ...

// Add a status bar background
self.statusBarBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width, 20.0f)];
self.statusBarBackground.backgroundColor = [UIColor blackColor];
self.statusBarBackground.alpha = 0.0;
self.statusBarBackground.userInteractionEnabled = NO;
self.statusBarBackground.layer.zPosition = 999; // Position its layer over all other views
[self.window addSubview:self.statusBarBackground];

// ...
return YES;

Następnie stworzyłem metodę wprowadzania / oddalania tła czarnego paska stanu:

- (void) showSolidStatusBar:(BOOL) solidStatusBar
{
    [UIView animateWithDuration:0.3f animations:^{
        if(solidStatusBar)
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
            self.statusBarBackground.alpha = 1.0f;
        }
        else
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
            self.statusBarBackground.alpha = 0.0f;
        }
    }];
}

Wszystko, co muszę teraz zrobić, to zadzwonić w [appDelegate showSolidStatusBar:YES]razie potrzeby.

Alexandre OS
źródło
2

Może to być przytłaczający problem, jeśli używasz układu automatycznego, ponieważ nie możesz już bezpośrednio manipulować ramkami. Istnieje proste rozwiązanie bez nadmiernej pracy.

Skończyło się na napisaniu metody użytkowej w klasie użytkowej i wywołałem ją ze wszystkich viewDidLayoutSubviewsmetod kontrolerów widoków .

+ (void)addStatusBarIfiOS7:(UIViewController *)vc
    {
        if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
            CGRect viewFrame = vc.view.frame;
            if(viewFrame.origin.y == 20) {
                //If the view's y origin is already 20 then don't move it down.
                return;
            }
            viewFrame.origin.y+=20.0;
            viewFrame.size.height-= 20.0;
            vc.view.frame = viewFrame;
            [vc.view layoutIfNeeded];
        }
    }

Zastąp viewDidLayoutSubviewsmetodę w kontrolerze widoku, gdzie chcesz pasek stanu. Przeprowadzi cię przez ciężar Autolayout.

- (void)viewDidLayoutSubviews
{
    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    [super viewDidLayoutSubviews];
    [MyUtilityClass addStatusBarIfiOS7:self];
}
Selvin
źródło
1

Najłatwiejszym sposobem jest zainstalowanie starszego zestawu SDK w najnowszym Xcode.

Jak zainstalować starszy SDK do najnowszego Xcode?

  1. Możesz pobrać zestaw iOS 6.1 SDK ze strony http://www.4shared.com/zip/NlPgsxz6/iPhoneOS61sdk.html lub pobrać starszy Xcode i pobrać zestaw SDK z jego zawartości

  2. Rozpakuj i wklej ten folder do /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs

  3. Uruchom ponownie kod xcode.

  4. U może teraz wybrać starszy zestaw SDK w ustawieniach kompilacji projektu

Mam nadzieję, że to ci pomoże. To zadziałało dla mnie =)

marcelosalloum
źródło
pracował dla mnie. dzięki @marcelosalloum, ale wciąż szukam obejścia dla mojej aplikacji phonegap (uiwebview) do obsługi przezroczystego paska stanu iOS7 do przyszłej aktualizacji mojej aplikacji. dzięki jeszcze raz. ;)
hanizm
@marcellosaloum, czy na pewno aplikacja zostanie zaakceptowana przez Apple? Powiedzieli, że aplikacje skompilowane za pomocą XCode 4 nie będą już akceptowane ... to w rzeczywistości oznacza SDK dla iOS 6.
Valerio,
Moja aplikacja została zaakceptowana, ponieważ Xcode5 może kompilować starsze zestawy SDK dla iOS. Nie jestem pewien, czy AppStore odrzuci wbudowane aplikacje Xcode4, ale (Xcode4! = IOS 6 SDK), jak powiedziałeś.
marcelosalloum
Czy to było po 1 lutego? W tym dniu Apple uczyniło to obowiązkowym.
Valerio,
Nie, ostatnio dotknąłem tego kodu w zeszłym roku, folk. Nie wiedziałem, że Apple uczyniło to obowiązkowym (choć nie jest szczęśliwy, że to wie). Czy mógłbyś zamieścić tutaj link, który to mówi? Pozdrawiam
marcelosalloum,
1

Jak za pomocą presentViewController:animated:completion:pomieszanegowindow.rootViewController.view , musiałem znaleźć inne podejście do tego problemu. W końcu udało mi się pracować z modami i rotacjami, podklasując UIView mojego rootViewController.

.h

@interface RootView : UIView

@end

.m

@implementation RootView

-(void)setFrame:(CGRect)frame
{
    if (self.superview && self.superview != self.window)
    {
        frame = self.superview.bounds;
        frame.origin.y += 20.f;
        frame.size.height -= 20.f;
    }
    else
    {
        frame = [UIScreen mainScreen].applicationFrame;
    }

    [super setFrame:frame];
}

- (void)layoutSubviews
{
    self.frame = self.frame;

    [super layoutSubviews];
}

@end

Masz teraz silne obejście animacji iOS7.

Cœur
źródło
1

Spóźniłem się na tę odpowiedź, ale chcę tylko podzielić się tym, co zrobiłem, co jest w zasadzie najłatwiejszym rozwiązaniem

Przede wszystkim-> Przejdź do info.plistpliku i dodaj Styl paska stanu-> Przezroczysty czarny styl (alfa 0,5)

Teraz idzie: -

Dodaj ten kod do AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
     //Whatever your code goes here
  if(kDeviceiPad){

     //adding status bar for IOS7 ipad
         if (IS_IOS7) {
              UIView *addStatusBar = [[UIView alloc] init];
              addStatusBar.frame = CGRectMake(0, 0, 1024, 20);
              addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //change this to match your navigation bar
              [self.window.rootViewController.view addSubview:addStatusBar];
                    }
                }
    else{

         //adding status bar for IOS7 iphone
        if (IS_IOS7) {
            UIView *addStatusBar = [[UIView alloc] init];
            addStatusBar.frame = CGRectMake(0, 0, 320, 20);
            addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //You can give your own color pattern
            [self.window.rootViewController.view addSubview:addStatusBar];
        }

    return YES;
   }
Vizllx
źródło
0

Moim bardzo prostym rozwiązaniem (zakładając, że obsługiwana jest tylko orientacja pionowa) jest ponowne zdefiniowanie granic okna aplikacji dla wersji iOS poniżej 7, w metodzie delegowanej aplikacji didFinishLaunchingWithOptions:

CGRect screenBounds = [[UIScreen mainScreen] bounds];
if ([HMService getIOSVersion] < 7) {
    // handling statusBar (iOS6) by leaving top 20px for statusbar.
    screenBounds.origin.y = 20;
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
else {
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
jki
źródło
Twój kod po prostu przesuwa „y” z 0 na 20, ale nie dostosowuje odpowiednio wysokości, więc powinieneś dodać screenBounds.size.height - = 20; zaraz po screenBounds.origin.y = 20;
Amit C.
0

Możesz ukryć pasek stanu razem. Twoja aplikacja będzie więc pełnoekranowa. Myślę, że to najlepsze, co dostaniesz.

UIStatusBarStyleNone lub ustaw w ustawieniach docelowych.

Christopher Rex
źródło
2
gdzie określić UIStatusbarstylenone
user4951
0

Kroki, aby ukryć pasek stanu w iOS 7:

1. Przejdź do pliku info.plist aplikacji.

2.I Ustaw, Wyświetl wygląd paska stanu na podstawie kontrolera: Boolean NO

Mam nadzieję, że rozwiązałem problem paska stanu .....

chandrika
źródło
0

Aby kontynuować pracę z setStatusBarHidden: Używam tej kategorii:

@interface UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden;

@end

@implementation UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden{
    if (!IOS7) {
        [self setStatusBarHidden:statusBarHidden];
        return;
     }

    if ([self isStatusBarHidden] == statusBarHidden) {
        return;
    }

    [self setStatusBarHidden:statusBarHidden];
    [self keyWindow].clipsToBounds = YES;
    CGFloat offset = statusBarHidden ? 0 : 20;
    [self keyWindow].frame =  CGRectMake(0,offset,[self keyWindow].frame.size.width,[self keyWindow].frame.size.height-offset);
    [self keyWindow].bounds = CGRectMake(0, offset, [self keyWindow].frame.size.width,[self keyWindow].frame.size.height);
}

@end
Tomer Even
źródło
0

To może być za późno na udostępnienie, ale mam coś, co może komuś pomóc, próbowałem podklasować UINavigationBar i chciałem, aby wyglądał jak iOS 6 z czarnym paskiem stanu i tekstem paska stanu w kolorze białym.

Oto, co znalazłem do tego

        self.navigationController?.navigationBar.clipsToBounds = true
        self.navigationController?.navigationBar.translucent = false
        self.navigationController?.navigationBar.barStyle = .Black
        self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()

Sprawiło, że moje tło paska stanu było czarne, tekst paska stanu biały, a pasek nawigacji biały.

iOS 9.3, XCode 7.3.1

channi
źródło