Jak programowo uzyskać wysokość paska stanu systemu iOS


277

Wiem, że obecnie pasek stanu (z czasem, baterią i połączeniem sieciowym) w górnej części iPhone'a / iPada to 20 pikseli dla ekranów bez siatkówki i 40 pikseli dla ekranów z siatkówką, ale na dowód mojej aplikacji chciałbym w przyszłości aby móc to ustalić bez wartości kodowania twardego. Czy można programowo obliczyć wysokość paska stanu?

Odpowiedzi:


506

[UIApplication sharedApplication].statusBarFrame.size.height. Ale ponieważ wszystkie rozmiary są wyrażone w punktach, a nie w pikselach, wysokość paska stanu zawsze wynosi 20.

Aktualizacja. Widząc, że ta odpowiedź jest uważana za pomocną, powinienem ją rozwinąć.

Wysokość paska stanu jest rzeczywiście równa 20,0 f punktów, z wyjątkiem następujących przypadków:

  • pasek stanu został ukryty setStatusBarHidden:withAnimation:metodą, a jego wysokość wynosi 0,0 punktu;
  • jak wskazano tutaj @Anton, podczas połączenia przychodzącego poza aplikacją Telefon lub podczas sesji nagrywania dźwięku wysokość paska stanu sesji wynosi 40,0 punktów.

Jest też przypadek paska stanu wpływającego na wysokość twojego widoku. Zwykle wysokość widoku jest równa wymiarowi ekranu dla danej orientacji minus wysokość paska stanu. Jeśli jednak animujesz pasek stanu (pokaż lub ukryj go) po wyświetleniu widoku, pasek stanu zmieni ramkę, ale widok nie , będziesz musiał ręcznie zmienić rozmiar widoku po animacji paska stanu (lub podczas animacji, ponieważ wysokość paska stanu ustawia się na wartość końcową na początku animacji).

Aktualizacja 2. Istnieje również przypadek orientacji interfejsu użytkownika. Pasek stanu nie respektuje wartości orientacji, dlatego wartość wysokości paska stanu dla trybu portretowego to [UIApplication sharedApplication].statusBarFrame.size.height(tak, domyślna orientacja to zawsze portret, bez względu na to, co mówi twoja aplikacja info.plist), dla krajobrazu - [UIApplication sharedApplication].statusBarFrame.size.width. Aby określić bieżącą orientację interfejsu użytkownika, gdy jest on niedostępny UIViewControlleri self.interfaceOrientationnie jest dostępny, użyj [UIApplication sharedApplication].statusBarOrientation.

Aktualizacja dla iOS7. Mimo zmiany stylu wizualnego paska stanu, nadal tam jest, jego ramka nadal zachowuje się tak samo. Jedyny ciekawy znalezisko o pasku mam - udział w I: Twój UINavigationBar„s kafelki tła również zostaną wyłożone na pasku stanu, dzięki czemu można osiągnąć ciekawe efekty projektu lub po prostu kolor paska stanu. To również nie wpłynie w żaden sposób na wysokość paska stanu.

Kafelkowe tło paska nawigacji jest również kafelkowane do paska stanu


6
Ta metoda daje 1024 (iOS7)
Marc

1
@MarcMosby, zobacz moją aktualizację. Pamiętasz ten problem - dzięki tobie.
Kyr Dunenkoff

2
Tak, jak wskazał Marc na iOS7, czasami generuje 1024, a czasem 20. Nie jest to więc głupi dowód na określenie wysokości. Wątpię, że dzieje się tak z powodu przezroczystego charakteru paska stanu w iOS 7. Możliwe, że najpierw przejdzie do pełnego ekranu, a następnie zmieni się sam. Jeśli więc zastosujesz zapytania podczas tego przejścia, możesz otrzymać niewłaściwą wartość. Może zadzwonić z tą metodą z opóźnieniem może pomóc w iOS 7.
Deepak GM,

1
Istnieje przypadek, w którym wysokość paska stanu może wynosić zero. Jeśli obsługiwaneInterfaceOrientations () zwracają UIInterfaceOrientation (niepoprawny wynik, ale nie występuje błąd kompilatora) zamiast UIInterfaceOrientationMask, a kontroler widoku jest prezentowany i zwalniany, wysokość paska stanu wyniesie zero.
Cymric

5
Również na pasku stanu iPhone X będzie wyższy.
przed

98

Idź z sugestią Martina do pytania: Uzyskaj wysokość paska stanu iPhone'a .

CGFloat AACStatusBarHeight()
{
    CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
    return MIN(statusBarSize.width, statusBarSize.height);
}

I w Swift

func statusBarHeight() -> CGFloat {
    let statusBarSize = UIApplication.shared.statusBarFrame.size
    return Swift.min(statusBarSize.width, statusBarSize.height)
}

To wygląda na włamanie, ale w rzeczywistości jest całkiem solidne. W każdym razie jest to jedyne działające rozwiązanie.

Stara odpowiedź

Poniższy kod, który wchodzi w twoją niestandardową podklasę UIViewController, prawie działał, by obsługiwać krajobraz. Ale zauważyłem skrzynkę narożną (podczas obracania z prawej> nieobsługiwany do góry nogami> z lewej), dla której nie działała (przełączona wysokość i szerokość).

BOOL isPortrait = self.interfaceOrientation == UIInterfaceOrientationPortrait;
CGSize statusBarSize = [UIApplication sharedApplication].statusBarFrame.size;
CGFloat statusBarHeight = (isPortrait ? statusBarSize.height : statusBarSize.width);

To nie jest poprawne. Wysokość paska stanu nie zmienia się po obróceniu urządzenia. Szerokość byłaby, ale powyższy kod tego nie pokazuje, podobnie jak pierwotne pytanie.
lehn0058

1
Masz rację, że „wysokość paska stanu nie zmienia się po obróceniu urządzenia”. Ale, jak odpowiedział Ash , „w trybie poziomym może się zdarzyć, że szerokość i wysokość zostaną zamienione”. Powyższy kod bierze to pod uwagę.
ma11hew28

To także interesujący problem, który teraz widziałem. Wygląda mi to na błąd po stronie Apple'a, ale wciąż należy go uwzględnić.
lehn0058

2
@ lehn0058 To nie jest błąd, to sposób, w jaki Apple obsługuje pasek wewnętrznie. Jest on przymocowany do okna i to okno jest obracane za pomocą transformacji. statusBarFrameJest zwracany jako wartość przed transformacji.
Leo Natan

1
Wygląda lepiej jako własność: Dvar statusBarHeight: CGFloat
Pablo A.,

23

Spróbuj tego:

CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;

1
wysokość zwracana w różnych orientacjach jest inna. to dziwne
tGilani,

1
Tak, jeśli rotacja jest pozioma - wartości [[UIApplication sharedApplication] statusBarFrame] .size.height i [[UIApplication sharedApplication] statusBarFrame] .size.width są przełączane.
Guntis Treulands

21

Swift 3 lub Swift 4:

UIApplication.shared.statusBarFrame.height

10

Chociaż pasek stanu ma zwykle 20 punktów wysokości, w niektórych sytuacjach może być dwa razy większy:

  • gdy jesteś w trakcie rozmowy telefonicznej (to dość powszechny scenariusz);
  • gdy dyktafon, Skype lub podobna aplikacja korzysta z mikrofonu w tle;
  • gdy aktywowany jest osobisty hotspot;

Po prostu spróbuj, a zobaczysz sam. Twarde kodowanie wysokości do 20 punktów będzie zwykle działać, dopóki nie zadziała.

Popieram więc odpowiedź H2CO3:

statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;

10

EDIT IOS 11 sposób wypracować gdzie umieścić górną część zawartości widzenia jest UIView za safeAreaLayoutGuideSee UIView Dokumentacja .

ODPOWIEDZIALNA ODPOWIEDŹ Jeśli celujesz w iOS 7+, dokumentacja dla UIViewController informuje, że topLayoutGuidewłaściwość viewController podaje dolną część paska stanu lub dolną część paska nawigacji, jeśli jest również widoczna. To może się przydać i na pewno jest mniej hackujące niż wiele poprzednich rozwiązań.


5

Nie zapominaj, że ramka paska stanu będzie w polu współrzędnych ekranu! Jeśli uruchomisz w trybie poziomym, może się okazać, że szerokość i wysokość zostaną zamienione. Zdecydowanie zalecamy użycie tej wersji kodu zamiast tego, jeśli obsługuje się orientację poziomą:

CGRect statusBarFrame = [self.window convertRect:[UIApplication sharedApplication].statusBarFrame toView:view];

Następnie możesz bezpośrednio odczytać właściwość height statusBarFrame. „Widok” w tym przypadku powinien być widokiem, w którym chcesz skorzystać z pomiarów, najprawdopodobniej kontrolera widoku głównego okna aplikacji.

Nawiasem mówiąc, pasek stanu może nie tylko być wyższy podczas połączeń telefonicznych, ale może również wynosić zero, jeśli pasek stanu został celowo ukryty.


To nie dało mi właściwej wysokości. Ale znalazłem inny sposób, który dla mnie działał: stackoverflow.com/a/16598350/242933
ma11hew28

Tak, to jest teraz dość stary kod, więc prawdopodobnie nie jest już poprawną odpowiedzią. Osobiście nie muszę już sprawdzać wysokości paska stanu dzięki automatycznemu układowi.
Ash


2

W systemie iOS 13 możesz użyć:

UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame.height

1
    var statusHeight: CGFloat!
    if #available(iOS 13.0, *) {
         statusHeight = UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame.height
    } else {
        // Fallback on earlier versions
        statusHeight = UIApplication.shared.statusBarFrame.height
    }


0

Właśnie znalazłem sposób, który pozwala ci nie uzyskiwać bezpośredniego dostępu do wysokości paska stanu, ale ją obliczyć.

Wysokość paska nawigacyjnego - topLayoutGuide length = wysokość paska stanu

Szybki:

let statusBarHeight = self.topLayoutGuide.length-self.navigationController?.navigationBar.frame.height

self.topLayoutGuide.lengthto górny obszar objęty półprzezroczystym paskiem i self.navigationController?.navigationBar.frame.heightjest to półprzezroczysty pasek bez paska stanu, który zwykle wynosi 44pkt. Korzystając z tej metody, można łatwo obliczyć wysokość paska stanu bez obawy o zmianę wysokości paska stanu z powodu połączeń telefonicznych.


To nie działa, self.topLayoutGuide.lengthwynosi 0, więc wynik kończy się na -44.
nambatee

@nambatee Wierzę, że to już nie działa, ponieważ jestem iOS 11 Apple używa safeAreaInsets
Henry Ngan


-6

Za pomocą następującego kodu jednowierszowego można uzyskać wysokość paska stanu w dowolnej orientacji, a także, jeśli jest widoczna, czy nie

#define STATUS_BAR_HIGHT (
    [UIApplicationsharedApplication].statusBarHidden ? 0 : (
        [UIApplicationsharedApplication].statusBarFrame.size.height > 100 ?
            [UIApplicationsharedApplication].statusBarFrame.size.width :
            [UIApplicationsharedApplication].statusBarFrame.size.height
    )
)

To proste, ale bardzo przydatne makro, po prostu spróbuj tego, nie musisz pisać żadnego dodatkowego kodu

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.