Як програмно отримати висоту рядка стану iOS


277

Я знаю, що наразі рядок стану (із часом, батареєю та мережевим підключенням) у верхній частині iPhone / iPad становить 20 пікселів для екранів, які не мають сітківки, і 40 пікселів для екранів сітківки, але я хотів би, щоб я підтвердив свою програму. щоб можна було визначити це без значень жорсткого кодування. Чи можливо програмно визначити висоту рядка стану?

Відповіді:


506

[UIApplication sharedApplication].statusBarFrame.size.height. Але оскільки всі розміри є в точках, а не в пікселях, висота рядка стану завжди дорівнює 20.

Оновлення. Вбачаючи, що ця відповідь вважається корисною, я повинен детально розглянути.

Висота рядка стану дійсно дорівнює 20,0f балів, за винятком таких випадків:

  • рядок стану приховано setStatusBarHidden:withAnimation:методом і його висота дорівнює 0,0f балів;
  • як вказувало @Anton, під час вхідного дзвінка за межами програми Phone або під час висоти смуги сеансу звукозапису висота дорівнює 40,0f балів.

Також є випадок рядка стану, який впливає на висоту перегляду. Зазвичай висота подання дорівнює розміру екрана для заданої орієнтації мінус висота смуги стану. Однак якщо ви анімуєте рядок стану (покажіть або приховати його) після того, як було показано подання, рядок стану змінить його кадр, але перегляд не буде , вам доведеться вручну змінити розмір подання після анімації рядка стану (або під час анімації, оскільки висота рядка статусу встановлює остаточне значення на початку анімації).

Оновлення 2. Також є випадок орієнтації на інтерфейс користувача. Рядок стану не відповідає значенню орієнтації, тому значення висоти рядка статусу для портретного режиму [UIApplication sharedApplication].statusBarFrame.size.height(так, орієнтація за замовчуванням завжди є портретною, незалежно від того, що говорить ваш додаток info.plist), для пейзажу - [UIApplication sharedApplication].statusBarFrame.size.width. Щоб визначити поточну орієнтацію інтерфейсу користувача, коли знаходиться поза UIViewControllerта self.interfaceOrientationнедоступна, використовуйте [UIApplication sharedApplication].statusBarOrientation.

Оновлення для iOS7. Незважаючи на те, що візуальний стиль рядка статусу змінився, він все ще є, його кадр все ще поводиться так само. Єдина цікава знахідка про рядку стану я - частина I: ваш UINavigationBar«и плиткового фон також буде кахельна рядок стану, так що ви можете досягти деяких цікавих дизайнерських ефектів , або просто кольору вашої рядка стану. Це теж ніяк не вплине на висоту смуги стану.

Фон з плиткою навігаційної панелі також викладений у рядку стану


6
Цей метод дає 1024 (iOS7)
Марк

1
@MarcMosby, дивіться моє оновлення. Згадав це питання - дякую вам.
Kyr Dunenkoff

2
Так, як Марк вказував на iOS7, він становить 1024 іноді і 20 разів. Отже, це вже не дурний спосіб визначення висоти. Сумніваюсь, це через прозорий характер рядка стану на iOS 7. Можливо, воно спочатку переходить на повний екран, а потім змінює розмір себе. Отже, якщо ви підходите до запитів під час цього переходу, ви можете отримати неправильне значення. Можливо, заклик цього методу із запізненням може допомогти на iOS 7.
Deepak GM

1
Існує випадок, коли висота рядка стану може бути нульовою. Якщо підтримуєтьсяInterfaceOrientations () повертає UIInterfaceOrientation (неправильний результат, але помилка компілятора) замість UIInterfaceOrientationMask, а контролер перегляду подається та відхиляється, висота рядка стану стане нульовою.
Cymric

5
Також на iPhone X рядок стану буде вище.
до

98

Перейдіть із пропозицією Мартіна до питання: Отримайте висоту смуги стану iPhone .

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

І в Свіфта

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

Здається, хак, але насправді досить солідний. У всякому разі, це єдине робоче рішення.

Стара відповідь

Наступний код, який би входив у ваш спеціальний підклас UIViewController, майже працював на підтримку пейзажу. Але я помітив кутовий корпус (при обертанні праворуч> непідтримуваний догори дном> ліворуч), для якого він не працював (перемикався по висоті та ширині).

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

Це неправильно. Висота рядка стану не змінюється при обертанні пристрою. Ширина буде, але наведений вище код не показує цього, а також це не було первинним питанням.
lehn0058

1
Ви маєте рацію, що "висота рядка стану не змінюється при обертанні пристрою". Але, як відповів Еш , "у ландшафтному режимі ви можете виявити, що ширина та висота змінюються". У наведеному вище коді це враховується.
ma11hew28

Це цікаве питання, яке я бачив і зараз. Мені це схоже на помилку на стороні Apple, але все одно потрібно враховувати.
lehn0058

2
@ lehn0058 Це не помилка, це те, як Apple обробляє планку всередині. Він прикріплюється до вікна, і це вікно обертається за допомогою перетворення. statusBarFrameПовертається в якості значення перед перетворенням.
Лев Натан

1
Це виглядає краще як власність: Dvar statusBarHeight: CGFloat
Пабло А.

23

Спробуйте це:

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

1
висота, що повертається в різних орієнтаціях, різна. це дивно
tGilani

1
Так, якщо обертання є альбомним - перемикаються значення [[UIApplication sharedApplication] statusBarFrame] .size.height та [[UIApplication sharedApplication] statusBarFrame] .size.width.
Guntis Treulands


10

Хоча рядок стану зазвичай високий 20 балів, у деяких ситуаціях він може бути вдвічі більшим:

  • коли ви посеред телефонного дзвінка (це досить поширений сценарій);
  • коли диктофон або Skype або подібний додаток використовують мікрофон у фоновому режимі;
  • коли активована Персональна точка доступу;

Просто спробуйте, і ви самі переконаєтесь. Жорстке кодування висотою до 20pt зазвичай працює, поки це не зробиться.

Тому я другий відповідь H2CO3:

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

10

РЕДАКТУВАННЯ IOS 11 спосіб визначити, де розмістити верхню частину вашого перегляду, - це safeAreaLayoutGuideперегляд документації UIView у розділі UIView .

ВІДМОВАНИЙ ВІДПОВІДЬ Якщо ви орієнтуєтесь на iOS 7+, Документація для UIViewController повідомляє, що властивість viewController topLayoutGuideнадає вам дно рядка стану або нижню частину навігаційної панелі, якщо вона також є видимою. Це може бути корисним, і, звичайно, менш злому, ніж багато попередніх рішень.


5

Не забувайте, що рамка рядка стану знаходитиметься в координатному просторі екрану! Якщо ви запускаєте в ландшафтному режимі, ви можете виявити, що ширина і висота змінюються. Настійно рекомендую замість цього використовувати цю версію коду, якщо ви підтримуєте пейзажні орієнтації:

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

Потім ви можете читати властивість висоти statusBarFrame безпосередньо. "Перегляд" у цьому випадку повинен бути представленням, у якому ви хочете використовувати вимірювання, швидше за все, контролером кореневого виду вікна програми.

Між іншим, рядок стану не тільки може бути вищим під час телефонних дзвінків, але також може бути нульовим, якщо рядок стану навмисно приховано.


Це не дало мені правильного зросту. Але, я знайшов інший спосіб , який працював для мене: stackoverflow.com/a/16598350/242933
ma11hew28

Так, це вже досить старий код, тому, ймовірно, вже не вірна відповідь. Особисто мені більше не виникає потреби перевіряти висоту рядка стану, завдяки автоматичному компонуванню.
Еш


2

Для iOS 13 можна використовувати:

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

Щойно я знайшов спосіб, який дозволяє вам не безпосередньо отримувати доступ до висоти рядка стану, а обчислювати його.

Висота смуги навігації - topLayoutGuide length = висота рядка стану

Швидкий:

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

self.topLayoutGuide.length- це верхня область, яка охоплюється напівпрозорою смугою, і self.navigationController?.navigationBar.frame.heightє напівпрозора смужка, що виключає смугу стану, яка, як правило, становить 44 пункти. Таким чином, використовуючи цей метод, ви можете легко обчислити висоту смуги стану, не турбуючись про зміну висоти смуги стану через телефонні дзвінки.


Це не працює, self.topLayoutGuide.lengthце 0, тому результат закінчується -44.
nambatee

@nambatee Я вважаю, що це більше не працює, тому що я iOS 11 Apple використовує safeAreaInsets
Генрі Нган


-6

Використовуючи наступний однорядковий код, ви можете отримати висоту рядка стану в будь-якій орієнтації, а також, якщо вона видна чи ні

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

Це просто простий, але дуже корисний макрос, просто спробуйте це не потрібно писати зайвий код

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.