Как узнать ширину и высоту экрана в iOS?


506

Как получить размеры экрана в iOS?

В настоящее время я использую:

lCurrentWidth = self.view.frame.size.width;
lCurrentHeight = self.view.frame.size.height;

в viewWillAppear:иwillAnimateRotationToInterfaceOrientation:duration:

Первый раз получаю весь экран размером. Во второй раз я получаю экран минус панель навигации.

Ответы:


1063

Как получить размеры экрана в iOS?

Проблема с кодом, который вы разместили, заключается в том, что вы рассчитываете на размер представления, соответствующий размеру экрана, и, как вы видели, это не всегда так. Если вам нужен размер экрана, вы должны посмотреть на объект, который представляет сам экран, например:

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;

Обновление для разделенного просмотра: В комментариях Дмитрий спросил:

Как я могу получить размер экрана в режиме разделенного просмотра?

Приведенный выше код сообщает размер экрана, даже в режиме разделенного экрана. Когда вы используете режим разделенного экрана, окно вашего приложения меняется. Если приведенный выше код не дает ожидаемой информации, то, как и OP, вы смотрите не на тот объект. В этом случае, однако, вы должны смотреть на окно вместо экрана, например так:

CGRect windowRect = self.view.window.frame;
CGFloat windowWidth = windowRect.size.width;
CGFloat windowHeight = windowRect.size.height;

Swift 4.2

let screenRect = UIScreen.main.bounds
let screenWidth = screenRect.size.width
let screenHeight = screenRect.size.height

// split screen            
let windowRect = self.view.window?.frame
let windowWidth = windowRect?.size.width
let windowHeight = windowRect?.size.height

7
Ориентация действительно управляется на уровне контроллера представления. Взгляните на Управление ориентацией интерфейса View Controller . Так что да, посмотрите на свойство interfaceOrientation вашего контроллера представления. Кстати, вы спросили о размере экрана, вот что я вам показал, но для отображения вашего контента вам, вероятно, следует использовать границы окна или рамки приложения, в зависимости от того, что вы делаете.
Калеб

2
полезно отметить, что это возвращает полную ширину экрана без отступов. Просто вычтите отступы вашего приложения (обычно по 20 с каждой стороны) из этих результатов, чтобы получить «полезное» пространство для большинства элементов
Ник Даугерти,

2
@NickDaugherty Да, в том-то и дело - ОП хотел размеры экрана. Место, куда вы помещаете объекты на экран, зависит только от вас и зависит от типа приложения, которое вы создаете. Например, если вы выводите на экран фотографию или игровой интерфейс, вы можете вообще не использовать отступы.
Калеб

3
Обратите внимание, что это возвращает значение, измеренное в пунктах. Так что, если вы ожидаете разрешение экрана в пикселях, результат будет неверным, и вы должны умножить результат на [UIScreen scale].
Robotbugs

3
Кто - то отметил, что с CGRect может иметь отрицательную ширину или высоту , мы должны использовать CGRectGetWidth()и CGRectGetHeight()вместо прямого доступа к sizeполю в прямоугольнике. Я не думаю, что это когда-либо будет проблемой в отношении прямоугольника экрана, но я полагаю, что об этом нужно знать.
Калеб

64

Осторожно, [UIScreen mainScreen] также содержит строку состояния, если вы хотите получить фрейм для вашего приложения (исключая строку состояния), вы должны использовать

+ (CGFloat) window_height   {
    return [UIScreen mainScreen].applicationFrame.size.height;
}

+ (CGFloat) window_width   {
    return [UIScreen mainScreen].applicationFrame.size.width;
}

4
не рекомендуется в ios 9.0
Zakaria Darwish,

6
поскольку applicationFrame устарела, замените наreturn [[UIScreen mainScreen] bounds].size.width;
lizzy81

44

Я перевел некоторые из приведенных выше ответов Objective-C на код Swift. Каждый перевод сопровождается ссылкой на оригинальный ответ.

Главный ответ

let screen = UIScreen.main.bounds
let screenWidth = screen.size.width
let screenHeight = screen.size.height

Простой ответ функции

func windowHeight() -> CGFloat {
    return UIScreen.mainScreen().applicationFrame.size.height
}

func windowWidth() -> CGFloat {
    return UIScreen.mainScreen().applicationFrame.size.width
}

Ориентация устройства Ответ

var screenHeight : CGFloat
let statusBarOrientation = UIApplication.sharedApplication().statusBarOrientation
// it is important to do this after presentModalViewController:animated:
if (statusBarOrientation != UIInterfaceOrientation.Portrait
    && statusBarOrientation != UIInterfaceOrientation.PortraitUpsideDown){
    screenHeight = UIScreen.mainScreen().applicationFrame.size.width
} else {
    screenHeight = UIScreen.mainScreen().applicationFrame.size.height
}

Журнал Ответ

let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
println("width: \(screenWidth)")
println("height: \(screenHeight)")

Похоже, что в журнале есть опечатка. Должно ли это быть UIScreen.mainScreen (). Bounds.size.width? Я получаю ошибку компиляции без ".bounds".
Камень

@skypecakes Я исправил ответ, включив ".bounds". Спасибо за ответ.
Мартин Вулстенхулм,

applicationFrame устарела в iOS 9 и выше, замените наreturn UIScreen.mainScreen().bounds].size.width
Suhaib

39

Я использовал эти удобные методы раньше:

- (CGRect)getScreenFrameForCurrentOrientation {
    return [self getScreenFrameForOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

- (CGRect)getScreenFrameForOrientation:(UIInterfaceOrientation)orientation {

    CGRect fullScreenRect = [[UIScreen mainScreen] bounds];

    // implicitly in Portrait orientation.
    if (UIInterfaceOrientationIsLandscape(orientation)) {
      CGRect temp = CGRectZero;
      temp.size.width = fullScreenRect.size.height;
      temp.size.height = fullScreenRect.size.width;
      fullScreenRect = temp;
    }

    if (![[UIApplication sharedApplication] statusBarHidden]) {
      CGFloat statusBarHeight = 20; // Needs a better solution, FYI statusBarFrame reports wrong in some cases..
      fullScreenRect.size.height -= statusBarHeight;
    }

    return fullScreenRect;
} 

Хорошее решение, но будьте осторожны, так как временное значение имеет неопределенное происхождение.
Семян

4
Вы получаете 0,0 по умолчанию? Когда я зарегистрировал fullScreenRect, он дал мне: {{8.03294e-35, 3.09816e-40}, {480, 320}}. Я выбрал инициализацию с помощью CGRect temp = CGRectZero;
Семян

1
UIInterfaceOrientationIsLandscape не обрабатывает UIDeviceOrientationFaceUp и UIDeviceOrientationFaceDown, которые могут быть возвращены из UIDevice.
Андрей

6
Вы можете использовать свойство screen.applicationFrame вместо screen.bounds, которое заботится о строке состояния.
Geraud.ch

Оказывается, в некоторых случаях applicationFrame не возвращает фрейм с правильно вычтенной строкой состояния (полноэкранные модалы из splitview)
Люк Макнейс

15

Я понимаю, что это старый пост, но иногда я нахожу его полезным для #define констант, подобных этим, поэтому мне не нужно беспокоиться об этом:

#define DEVICE_SIZE [[[[UIApplication sharedApplication] keyWindow] rootViewController].view convertRect:[[UIScreen mainScreen] bounds] fromView:nil].size

Вышеуказанная константа должна возвращать правильный размер независимо от ориентации устройства. Тогда получить размеры так же просто, как:

lCurrentWidth = DEVICE_SIZE.width;
lCurrentHeight = DEVICE_SIZE.height;

Возможно, вы захотите основать макрос на ответе AnswerBot, поскольку это кажется лучшим ответом.
Griotspeak

13

Очень легко получить размер вашего устройства, а также принять во внимание ориентацию:

// grab the window frame and adjust it for orientation
UIView *rootView = [[[UIApplication sharedApplication] keyWindow] 
                                   rootViewController].view;
CGRect originalFrame = [[UIScreen mainScreen] bounds];
CGRect adjustedFrame = [rootView convertRect:originalFrame fromView:nil];

Привет, я использую это в viewDidLoad в приложении только для iPad, есть ли причина, почему оно получает правильное значение в первый раз, затем значение «переворачивается» при каждой загрузке после, то есть оно читает его как первый взгляд lanscape, затем я переместиться в сторону и вернуться к представлению, и кажется, что оно читается как портрет, даже если ориентация не была изменена? Спасибо
Крейгк

@LukeMcneice В моем производственном коде у меня есть утверждение, чтобы удостовериться, что фрейм найден ... У меня еще нет этого утверждения. Что возвращается для rootView и originalFrame?
памятники

Я использую эту технику в одиночном, чтобы получить ширину / высоту с поправкой на ориентацию. Однако, если этот код выполняется, в то время как окно UIAlert, показывающее convertRect, возвращает AdjustFrame с размером (по крайней мере, шириной) 0. Любые мысли, что происходит с этим?
Electro-Bunny

Ах. An UIAlertViewвставит себя как представление rootViewController keyWindow. У меня есть логика, которая избегает углового случая, потому что, если представление предупреждения включено, пользователь не может взаимодействовать с клавиатурой, поэтому обычно нет необходимости захватывать кадр клавиатуры в это время.
памятники

Спасибо за понимание. Я использовал твою технику в баннерной рекламе. Это был простой и приятный способ сообщить ad api размер рамки экрана для нового объявления. Так как я не смогу взаимно исключать рекламные баннеры и UIAlert, я, скорее всего, вернусь к обнаружению переключения ландшафта и портрета и прямого перебора x / y по мере необходимости.
Electro-Bunny

9

Мы также должны учитывать ориентацию устройства:

CGFloat screenHeight;
// it is important to do this after presentModalViewController:animated:
if ([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortraitUpsideDown){
    screenHeight = [UIScreen mainScreen].applicationFrame.size.height;
}
else{
    screenHeight = [UIScreen mainScreen].applicationFrame.size.width;
}

Хорошее решение Я сделал это, чтобы приложение iPad работало в горизонтальной ориентации из встроенного контроллера представления при представлении модального VC.
StackRunner


5

Здесь я обновил для Swift 3

applicationFrame устарела из iOS 9

В быстрой версии они удалили () и несколько изменили соглашение об именах, вы можете обратиться сюда Ссылка

func windowHeight() -> CGFloat {
    return UIScreen.main.bounds.size.height
}

func windowWidth() -> CGFloat {
    return UIScreen.main.bounds.size.width
}

4

Современный ответ:

если ваше приложение поддерживает разделенное представление на iPad, эта проблема немного усложняется. Вам нужен размер окна, а не экран, который может содержать 2 приложения. Размер окна также может меняться во время работы.

Используйте размер главного окна приложения:

UIApplication.shared.delegate?.window??.bounds.size ?? .zero

Примечание. Приведенный выше метод может получить неправильное значение, прежде чем окно станет ключевым при запуске. если вам нужна только ширина, очень рекомендуется метод ниже :

UIApplication.shared.statusBarFrame.width

Использование старого решения UIScreen.main.boundsвернет границы устройства. Если ваше приложение работает в режиме разделенного просмотра, оно получит неправильные размеры.

self.view.window в самом горячем ответе может получиться неправильный размер, когда приложение содержит 2 или более окон, а окно имеет небольшой размер.


4

Используйте их, Structsчтобы узнать полезную информацию о текущем устройстве в Swift 3.0

struct ScreenSize { // Answer to OP's question

    static let SCREEN_WIDTH         = UIScreen.main.bounds.size.width
    static let SCREEN_HEIGHT        = UIScreen.main.bounds.size.height
    static let SCREEN_MAX_LENGTH    = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
    static let SCREEN_MIN_LENGTH    = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)

}

struct DeviceType { //Use this to check what is the device kind you're working with

    static let IS_IPHONE_4_OR_LESS  = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
    static let IS_IPHONE_SE         = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
    static let IS_IPHONE_7          = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
    static let IS_IPHONE_7PLUS      = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
    static let IS_IPHONE_X          = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
    static let IS_IPAD              = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0

}


struct iOSVersion { //Get current device's iOS version

    static let SYS_VERSION_FLOAT  = (UIDevice.current.systemVersion as NSString).floatValue
    static let iOS7               = (iOSVersion.SYS_VERSION_FLOAT >= 7.0 && iOSVersion.SYS_VERSION_FLOAT < 8.0)
    static let iOS8               = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0)
    static let iOS9               = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0)
    static let iOS10              = (iOSVersion.SYS_VERSION_FLOAT >= 10.0 && iOSVersion.SYS_VERSION_FLOAT < 11.0)
    static let iOS11              = (iOSVersion.SYS_VERSION_FLOAT >= 11.0 && iOSVersion.SYS_VERSION_FLOAT < 12.0)
    static let iOS12              = (iOSVersion.SYS_VERSION_FLOAT >= 12.0 && iOSVersion.SYS_VERSION_FLOAT < 13.0)

}

3

Если вы хотите ширину / высоту экрана независимо от ориентации устройства (подходит для определения размера только портретных контроллеров, запускаемых из альбомной ориентации):

CGFloat screenWidthInPoints = [UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale;
CGFloat screenHeightInPoints = [UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale;

[UIScreen mainScreen] .nativeBounds <- Из документов -> Ограничительный прямоугольник физического экрана, измеренный в пикселях. Этот прямоугольник основан на устройстве в портретной ориентации. Это значение не изменяется при вращении устройства.


2

Вот быстрый способ получить размеры экрана:

print(screenWidth)
print(screenHeight)

var screenWidth: CGFloat {
    if UIInterfaceOrientationIsPortrait(screenOrientation) {
        return UIScreen.mainScreen().bounds.size.width
    } else {
        return UIScreen.mainScreen().bounds.size.height
    }
}

var screenHeight: CGFloat {
    if UIInterfaceOrientationIsPortrait(screenOrientation) {
        return UIScreen.mainScreen().bounds.size.height
    } else {
        return UIScreen.mainScreen().bounds.size.width
    }
}

var screenOrientation: UIInterfaceOrientation {
    return UIApplication.sharedApplication().statusBarOrientation
}

Они включены в качестве стандартной функции в:

https://github.com/goktugyil/EZSwiftExtensions



1

Swift 3.0

для ширины

UIScreen.main.bounds.size.width

для высоты

UIScreen.main.bounds.size.height

-2

Вы можете поместить эти макросы в ваш файл pch и использовать их в любом месте проекта, используя "SCREEN_WIDTH"

#define SCREEN_WIDTH                ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height)

и "SCREEN_HEIGHT"

#define SCREEN_HEIGHT               ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation ==   UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width)

Пример использования:

CGSize calCulateSizze ;
calCulateSizze.width = SCREEN_WIDTH/2-8;
calCulateSizze.height = SCREEN_WIDTH/2-8;

Можете ли вы сделать отступ для своего кода в соответствии с форматом уценки? В настоящее время это было помечено как "низкое качество" пользователями сообщества в очереди на проверку.
Манодж Кумар
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.