Как программно получить высоту строки состояния 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, посмотрите мое обновление. Вспомнил этот вопрос - спасибо вам.
Кыр Дуненков

2
Да, как указал Марк на iOS7, иногда получается 1024, а иногда 20. Так что это уже не надежный способ определения высоты. Я сомневаюсь, что это из-за прозрачного характера строки состояния на iOS 7. Может случиться так, что сначала он переходит в полноэкранный режим, а затем изменяет размеры. Поэтому, если вы применяете запросы во время этого перехода, вы можете получить неправильное значение. Может быть, вызов этого метода с задержкой может помочь на iOS 7.
Deepak GM

1
Есть случай, когда высота строки состояния может быть нулевой. Если supportInterfaceOrientations () возвращает UIInterfaceOrientation (неверный результат, но нет ошибки компилятора) вместо UIInterfaceOrientationMask, и viewcontroller представляется и отклоняется, высота строки состояния становится равной нулю.
Цимрик

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

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

  • когда вы находитесь в середине телефонного звонка (это довольно распространенный сценарий);
  • когда диктофон, или Skype, или подобное приложение, использует микрофон в фоновом режиме;
  • когда активирована личная точка доступа;

Просто попробуйте, и вы сами убедитесь. Жесткое кодирование высоты до 20pt обычно будет работать, пока не сработает.

Итак, я второй ответ H2CO3:

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

10

РЕДАКТИРОВАТЬ iOS 11 способ определить, где разместить верхнюю часть содержимого вашего просмотра, - safeAreaLayoutGuideсм. Документацию UIView в разделе UIView .

УСТАРЕВШИЙ ОТВЕТ Если вы ориентируетесь на iOS 7+, в документации для UIViewController указано, что topLayoutGuideсвойство viewController дает вам нижнюю часть строки состояния или нижнюю часть панели навигации, если она также видна. Это может быть полезно, и, конечно, менее взломать, чем многие из предыдущих решений.


5

Не забывайте, что рамка строки состояния будет в координатном пространстве экрана! Если вы запускаете в ландшафтном режиме, вы можете обнаружить, что ширина и высота меняются местами. Я настоятельно рекомендую вам использовать эту версию кода, если вы поддерживаете альбомную ориентацию:

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

После этого вы можете напрямую прочитать свойство высоты statusBarFrame. «Представление» в этом случае должно быть представлением, в котором вы хотите использовать измерения, скорее всего, корневым контроллером окна приложения.

Кстати, строка состояния может быть не только выше во время телефонных звонков, но также может быть нулевой, если строка состояния была намеренно скрыта.


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

Да, это довольно старый код, так что, вероятно, он больше не является правильным ответом. Лично мне больше не нужно проверять высоту строки состояния, благодаря автоматической раскладке.
Эш


2

Вот быстрый способ получить высоту строки состояния экрана:

var screenStatusBarHeight: CGFloat {
    return UIApplication.sharedApplication().statusBarFrame.height
}

Они включены в качестве стандартной функции в моем проекте: https://github.com/goktugyil/EZSwiftExtensions


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 = высота строки состояния

Swift:

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.