iOS 7 - Pasek stanu nakłada się na widok

109

Mam, ViewControllerktóry jest wewnątrz a UINavigationcontroller, ale pasek nawigacji jest ukryty. Kiedy uruchamiam aplikację na iOS 7, pasek stanu pojawia się u góry mojego widoku. Czy jest sposób, aby tego uniknąć?

Nie chcę pisać żadnego kodu specyficznego dla systemu operacyjnego.

Tutaj wprowadź opis obrazu

Próbowałem ustawienie View controller-based status bar appearancesię NO, ale to nie rozwiąże problemu.

aryaxt
źródło
Opublikowałem swoją odpowiedź, aby wyświetlić pasek stanu, taki jak iOS 6, w iOS 7 stackoverflow.com/questions/18294872/…
Desert Rose
2
Aby rozwiązać problem z paskiem stanu, musisz również dostosować wartość początkową i delta Y. Może to pomóc w stackoverflow.com/q/18980925/1545180
Ganapathy

Odpowiedzi:

95

Xcode 5 ma iOS 6/7 Deltasspecjalnie stworzony do rozwiązania tego problemu. W scenorysie przeniosłem moje widoki o 20 pikseli w dół, aby wyglądały dobrze na iOS 7 i aby był kompatybilny z iOS 6, zmieniłem Delta yna -20.

wprowadź opis obrazu tutaj

Ponieważ moja storyboard nie korzysta z automatycznego układu, w celu zmiany rozmiaru wysokość poglądów prawidłowo na iOS 6 musiałem ustawić Delta heightjak również Delta Y.

aryaxt
źródło
8
Twoja odpowiedź jest prawidłowa, ale nie działa z wyświetlaczem 4 ". Zaktualizuj swoją odpowiedź, jeśli możesz sprawić, by działała również na wyświetlaczu 4". Z góry dziękuję.
2
@AnkitMehta Nie musiałem robić nic konkretnego dla 4
calowych iPhone'ów
5
pracował dla mnie. Zauważ, że aby zobaczyć te delty, musisz odznaczyć opcję „Użyj automatycznego układu” w obszarze „Tożsamość i typ” dla scenorysu.
marsant
2
Dowiedziałem się, że oprócz ustawienia -20 dla ∆Y, musiałem również ustawić +20 na ∆Height
Toland Hon.
3
Co się stanie, gdy zmieni się wysokość paska stanu? Np .: kiedy użytkownik aktywuje hot-spot, itp .... wtedy wysokość 40px ...
Łukasz
69

Jeśli po prostu NIE chcesz żadnego paska stanu, musisz zaktualizować plist o te dane: Aby to zrobić, w pliku plist dodaj te 2 ustawienia:

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

W systemie iOS 7 oczekuje się, że projekt aplikacji zostanie zaprojektowany z uwzględnieniem nałożonego przezroczystego paska stanu. Zobacz na przykład nową aplikację Pogoda na iOS 7.

Nathan H.
źródło
3
Jest to właściwie jedyna dobra odpowiedź, ponieważ rozwiązuje problem u jego podstaw w sposób, w jaki miał być zrobiony. A więc: potrzebne głosy za!
jedenaście59
5
Może to być odpowiednie w niektórych sytuacjach, ale chcesz bardzo ostrożnie ukrywać pasek stanu. Tylko w przypadku widoków pełnoekranowych, takich jak odtwarzacze multimedialne lub przeglądarki obrazów.
smileBot
1
@ eleven59, masz na myśli sposób, w jaki zamierzają autokraci w Apple.
JohnK
1
Zdecydowanie lepiej niż zmiana przesunięcia kontrolera widoku (który jest naprawdę brudny).
Benjamin Oman
ukrywanie paska statusu nie jest dobrym pomysłem ... Wiem, że to najłatwiejszy sposób obsługi iOS 7, ale czas jest POTRZEBNY ...
Fahim Parkar
43

Jest to domyślne zachowanie UIViewControllerw systemie iOS 7. Widok będzie pełnoekranowy, co oznacza, że ​​pasek stanu będzie zakrywał górną część widoku.

Jeśli masz UIViewControllerwewnątrz a, UINavigationControllera navigationBar jest widoczny, możesz mieć następujący kod w swoim viewDidLoadlub mieć obraz tła dla navigationBar.

self.edgesForExtendedLayout = UIRectEdgeNone;

Jeśli masz ukryty NavigationBar, musisz dostosować wszystkie elementy UIView, przesuwając o 20 punktów. Nie widzę innego rozwiązania. Użyj układu automatycznego, aby trochę pomóc.

Oto przykładowy kod do wykrywania wersji systemu iOS, jeśli chcesz zachować zgodność z poprzednimi wersjami.

NSUInteger DeviceSystemMajorVersion() {
    static NSUInteger _deviceSystemMajorVersion = -1;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        _deviceSystemMajorVersion = [[systemVersion componentsSeparatedByString:@"."][0] intValue];
    });

   return _deviceSystemMajorVersion;
}
Vincent
źródło
18
Zamiast pobierać, analizować i porównywać wersję systemu, zaleca się użycieif ([self respondsToSelector:@selector(edgesForExtendedLayout)])
Sebastian Hojas
15

Jedyne działające rozwiązanie, które stworzyłem samodzielnie.

Oto moja podklasa UIViewController https://github.com/comonitos/ios7_overlaping

1 Podklasa z UIViewController

2 Utwórz podklasę window.rootViewController z tej klasy.

3 Voila!

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect screen = [[UIScreen mainScreen] bounds];
        if (self.navigationController) {
            CGRect frame = self.navigationController.view.frame;
            frame.origin.y = 20;
            frame.size.height = screen.size.height - 20;
            self.navigationController.view.frame = frame;
        } else {
            if ([self respondsToSelector: @selector(containerView)]) {
                UIView *containerView = (UIView *)[self performSelector: @selector(containerView)];

                CGRect frame = containerView.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                containerView.frame = frame;
            } else {
                CGRect frame = self.view.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                self.view.frame = frame;
            }
        }
    }
}

4 Dodaj to, aby pasek stanu był biały Zaraz po [self.window makeKeyAndVisible]; !!!

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
comonitos
źródło
ale to nie pokazuje czasu na górze ... Największa wada ... :(
Fahim Parkar
Działa świetnie, ale w kroku 4 powinieneś użyć preferowanegoStatusBarStyle w kontrolerze widoku, ponieważ setStatusBarStyle jest przestarzały, a jego domyślną akcją jest nic nie robić. stackoverflow.com/a/19014724/1192732
CpnCrunch,
13
-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

-(void)viewWillLayoutSubviews{

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
  {
    self.view.clipsToBounds = YES;
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenHeight = 0.0;
    if(UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
        screenHeight = screenRect.size.height;
    else
        screenHeight = screenRect.size.width;
    CGRect screenFrame = CGRectMake(0, 20, self.view.frame.size.width,screenHeight-20);
    CGRect viewFrame1 = [self.view convertRect:self.view.frame toView:nil];
    if (!CGRectEqualToRect(screenFrame, viewFrame1))
    {
        self.view.frame = screenFrame;
        self.view.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    }
  }
}

Dodaj klucz w plist --- Wyświetl wygląd paska stanu opartego na kontrolerze: NIE

Darshit Shah
źródło
w razie
potrzeby
Dzięki, to rozwiązało mój nakładający się problem. Ale wciąż jest jeden problem - Wyświetl wygląd paska stanu opartego na kontrolerze: Myślę, że NIE jest to ukrycie paska stanu. Ale kiedy ustawię go na TAK, to nie wyświetla paska stanu, a kiedy ustawię go na NIE, pokazuje pasek stanu. Więc proszę, powiedz mi, czy mylę się z koncepcją, czy co?
Nayan,
1
Myślę, ponieważ weź domyślny półprzezroczysty kolor ustawiony w didFinishLaunchingWithOptions 'self.window.backgroundColor = [UIColor blueColor];' i ustaw w plist Wyświetl wygląd paska stanu na podstawie kontrolera TAK
Darshit Shah
Fajnie dzięki! Ponadto wystarczy zaznaczyć, że dokumentacja firmy Apple zaleca sprawdzanie za pomocą if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1) {} else {}. Twoje zdrowie!
Joel Balmer
Dziękuję bardzo. Twój kod jest dla nas bardzo pomocny. Proszę o wyjaśnienie funkcji viewWillLayoutSubviews.
user3182143
4

Aby ukryć pasek stanu w ios7, wykonaj następujące proste kroki:

W Xcode przejdź do Resourcesfolderu „ ” i otwórz „ (app name)-Info.plist file”.

  • sprawdź View controller based status bar appearanceklucz „ ” i ustaw jego wartość „ NO
  • sprawdź Status bar is initially hiddenklucz „ ” i ustaw jego wartość „ YES

Jeśli nie ma tam kluczy, możesz je dodać, wybierając „ information property list” u góry i klikając ikonę +

Mandeep Pasbola
źródło
Przeczytaj wyraźnie pytanie, nie prosił o całkowite ukrycie paska stanu.
ShayanK
1
@AspersionCast: Zapytał: „Czy jest sposób, aby tego uniknąć?” i jest to jeden ze sposobów uniknięcia tego.
Mandeep Pasbola
3

Jeśli używasz xibs, bardzo prostą implementacją jest hermetyzacja wszystkich podglądów podrzędnych w widoku kontenera z flagami zmiany rozmiaru (których będziesz już używać do zgodności 3,5 "i 4") , aby hierarchia widoku wyglądała mniej więcej tak

heirarchia xib

a potem viewDidLoadzrób coś takiego:

- (void)viewDidLoad
{
  [super viewDidLoad];
  // initializations
  if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) // only for iOS 7 and above
  {
    CGRect frame = containerView.frame;
    frame.origin.y += 20;
    frame.size.height -= 20;
    containerView.frame = frame;
  }
}

W ten sposób końcówki nie muszą być modyfikowane w celu zapewnienia zgodności z systemem iOS 7. Jeśli masz tło, możesz je trzymać na zewnątrz containerViewi pozwolić, aby obejmowało cały ekran.

tipycalFlow
źródło
3

To wszystko, co jest potrzebne, aby usunąć pasek stanu. wprowadź opis obrazu tutaj

Tony
źródło
2

W przypadku paska nawigacji:

Pisanie tego kodu:

self.navigationController.navigationBar.translucent = NO;

właśnie załatwił mi sprawę.

Saru
źródło
1

Odpowiedzi Vincenta na krawędzie ForExtendedLayout zadziałały dla mnie.

Te makra pomagają w określaniu wersji systemu operacyjnego, ułatwiając to

// 7.0 and above 
#define IS_DEVICE_RUNNING_IOS_7_AND_ABOVE() ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending) 

// 6.0, 6.0.x, 6.1, 6.1.x
#define IS_DEVICE_RUNNING_IOS_6_OR_BELOW() ([[[UIDevice currentDevice] systemVersion] compare:@"6.2" options:NSNumericSearch] != NSOrderedDescending) 

dodaj te makra do pliku prefix.pch projektu i możesz uzyskać do nich dostęp w dowolnym miejscu

if(IS_DEVICE_RUNNING_IOS_7_AND_ABOVE())
{
 //some iOS 7 stuff
 self.edgesForExtendedLayout = UIRectEdgeNone;
}

if(IS_DEVICE_RUNNING_IOS_6_OR_BELOW())
{
 // some old iOS stuff
}
RamaKrishna Chunduri
źródło
1
dla mnie self.edgesForExtendedLayout = UIRectEdgeNone; nie działa ... z jakiegoś powodu?
Fahim Parkar
1

Opublikowałem swoją odpowiedź na inny post z tym samym pytaniem z tym.

Z Przewodnika przejścia na Apple iOS7, https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/AppearanceCustomization.html#//apple_ref/doc/uid/TP40013174-CH15-SW1

Konkretnie automaticallyAdjustsScrollViewInsets=YESi set self.edgesForExtendedLayout = UIRectEdgeNonepracuje dla mnie, kiedy nie chce się do nakładania i mam tableviewcontroller.

Liangjun
źródło
0

Jeśli chcesz, aby opcja „Użyj automatycznego układu” była włączona za wszelką cenę, umieść następujący kod w pliku viewdidload.

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
{
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.extendedLayoutIncludesOpaqueBars = NO;
        self.automaticallyAdjustsScrollViewInsets = NO;
}
Ali Shahid
źródło
0

Mój pasek stanu i pasek nawigacji nakładają się na siebie po powrocie z widoku poziomego YTPlayer. Oto moje rozwiązanie po wypróbowaniu wersji @comonitos, ale nie działa na moim iOS 8

- (void)fixNavigationBarPosition {
    if (self.navigationController) {
        CGRect frame = self.navigationController.navigationBar.frame;
        if (frame.origin.y != 20.f) {
            frame.origin.y = 20.f;
            self.navigationController.navigationBar.frame = frame;
        }
    }
}

Po prostu wywołaj tę funkcję, gdy chcesz naprawić pozycję paska nawigacji. Zadzwoniłem na YTPlayerViewDelegate'splayerView:didChangeToState:

- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state {
    switch (state) {
        case kYTPlayerStatePaused:
        case kYTPlayerStateEnded:
            [self fixNavigationBarPosition];
            break;
        default:
    }
}
John Pang
źródło