Как получить ориентацию по высоте и ширине экрана?
Я пытаюсь программно определить текущую высоту и ширину моего приложения. Я использую это:
CGRect screenRect = [[UIScreen mainScreen] bounds];
Но это дает ширину 320 и высоту 480, независимо от того, находится ли устройство в портретной или альбомной ориентации. Как определить текущую ширину и высоту (т.е. Зависит от ориентации устройства) моего основного экрана?
Ответы
Ответ 1
Вы можете использовать что-то вроде UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)
для определения ориентации, а затем использовать соответствующие размеры.
ОДНАКО, во время изменения ориентации, как в UIViewController
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
Используйте ориентацию, переданную в toInterfaceOrientation
, поскольку статус UApplicationBarOrientation будет по-прежнему указывать на прежнюю ориентацию, поскольку она еще не изменилась (поскольку вы находитесь внутри обработчика событий will
).
Резюме
К этому относится несколько связанных должностей, но каждый из них, по-видимому, указывает, что вам нужно:
- Посмотрите
[[UIScreen mainScreen] bounds]
, чтобы получить размеры,
- Проверьте, в какой ориентации вы находитесь, и
- Учетная запись для высоты строки состояния (если показана)
Ссылки
Рабочий код
Обычно я не зашел так далеко, но вы заинтересовали меня. Следующий код должен сделать трюк. Я написал категорию по UIApplication. Я добавил методы класса для получения currentSize или размера в заданной ориентации, что вы бы назвали в UIViewController willRotateToInterfaceOrientation:duration:
.
@interface UIApplication (AppDimensions)
+(CGSize) currentSize;
+(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation;
@end
@implementation UIApplication (AppDimensions)
+(CGSize) currentSize
{
return [UIApplication sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation];
}
+(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation
{
CGSize size = [UIScreen mainScreen].bounds.size;
UIApplication *application = [UIApplication sharedApplication];
if (UIInterfaceOrientationIsLandscape(orientation))
{
size = CGSizeMake(size.height, size.width);
}
if (application.statusBarHidden == NO)
{
size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height);
}
return size;
}
@end
Чтобы использовать код простого вызова [UIApplication currentSize]
. Кроме того, я запускал приведенный выше код, поэтому я знаю, что он работает и сообщает правильные ответы во всех ориентациях. Обратите внимание, что я ставлю строку состояния. Интересно, что мне пришлось вычесть MIN для высоты и ширины строки состояния.
Надеюсь, это поможет.: D
Другие мысли
Вы можете получить размеры, посмотрев на свойство UIWindow rootViewController
. Я смотрел на это в прошлом, и он аналогично сообщает о тех же размерах как в портрете, так и в ландшафте, за исключением того, что отчеты имеют поворотное преобразование:
(gdb) po [[[[UIApplication sharedApplication] keyWindow] rootViewController] view]
< UILayoutContainerView: 0xf7296f0; frame = (0 0, 320 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = W + H; layer = < CALayer: 0xf729b80 >
(gdb) po [[[[UIApplication sharedApplication] keyWindow] rootViewController] view]
< UILayoutContainerView: 0xf7296f0; frame = (0 0; 320 480); AUTORESIZE = W + H; layer = < CALayer: 0xf729b80 >
Не знаете, как работает ваше приложение, но если вы не используете какой-либо навигационный контроллер, у вас может быть UIView под вашим основным видом с максимальной высотой/шириной родительского элемента и с ростом/ростом с родителем. Тогда вы можете сделать: [[[[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] subviews] objectAtIndex:0] frame]
. Это выглядит довольно интенсивно на одной линии, но вы получаете идею.
Однако... Было бы лучше сделать вышеуказанные 3 шага под сводкой. Начните возиться с UIWindows, и вы обнаружите странные вещи, например, отображение UIAlertView изменит ключевое слово UIApplication, чтобы указать на новый UIWindow, созданный UIAlertView. Кто знал? После обнаружения ошибки, основанной на keyWindow, я обнаружил, что это так изменилось!
Ответ 2
Это мой код решения! Этот метод может добавить к классу классов NSObject Categroy, или вы можете определить класс Top UIViewController и позволить всем вашим другим UIViewControllers наследовать его.
-(CGRect)currentScreenBoundsDependOnOrientation
{
CGRect screenBounds = [UIScreen mainScreen].bounds ;
CGFloat width = CGRectGetWidth(screenBounds) ;
CGFloat height = CGRectGetHeight(screenBounds) ;
UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){
screenBounds.size = CGSizeMake(width, height);
}else if(UIInterfaceOrientationIsLandscape(interfaceOrientation)){
screenBounds.size = CGSizeMake(height, width);
}
return screenBounds ;
}
Примечание, после IOS8, как Apple Document свойства UIScreen bounds говорит:
Обсуждение
Этот прямоугольник задается в текущем координатном пространстве, что учитывает любые повороты интерфейса для устройства. Поэтому значение этого свойства может измениться, когда устройство вращается между портретной и альбомной ориентацией.
поэтому для рассмотрения совместимости мы должны определить версию IOS и внести изменения, как показано ниже:
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
-(CGRect)currentScreenBoundsDependOnOrientation
{
CGRect screenBounds = [UIScreen mainScreen].bounds ;
if(IsIOS8){
return screenBounds ;
}
CGFloat width = CGRectGetWidth(screenBounds) ;
CGFloat height = CGRectGetHeight(screenBounds) ;
UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){
screenBounds.size = CGSizeMake(width, height);
}else if(UIInterfaceOrientationIsLandscape(interfaceOrientation)){
screenBounds.size = CGSizeMake(height, width);
}
return screenBounds ;
}
Ответ 3
Вот удобный макрос:
#define SCREEN_WIDTH (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height)
#define SCREEN_HEIGHT (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width)
Ответ 4
В iOS 8+ вы должны использовать метод viewWillTransitionToSize:withTransitionCoordinator
:
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// You can store size in an instance variable for later
currentSize = size;
// This is basically an animation block
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Get the new orientation if you want
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
// Adjust your views
[self.myView setFrame:CGRectMake(0, 0, size.width, size.height)];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Anything else you need to do at the end
}];
}
Это заменяет метод устаревших анимаций, который не дал информации о размере:
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
Ответ 5
В настоящее время параметры экрана iOS 8 верны для текущей ориентации. Это означает, что iPad в альбомной ориентации [UIScreen mainScreen].bounds вернет 768 на iOS <= 7 и 1024 на iOS 8.
Следующее возвращает правильную высоту и ширину для всех выпущенных версий.
-(CGRect)currentScreenBoundsDependOnOrientation
{
NSString *reqSysVer = @"8.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
return [UIScreen mainScreen].bounds;
CGRect screenBounds = [UIScreen mainScreen].bounds ;
CGFloat width = CGRectGetWidth(screenBounds) ;
CGFloat height = CGRectGetHeight(screenBounds) ;
UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){
screenBounds.size = CGSizeMake(width, height);
NSLog(@"Portrait Height: %f", screenBounds.size.height);
}else if(UIInterfaceOrientationIsLandscape(interfaceOrientation)){
screenBounds.size = CGSizeMake(height, width);
NSLog(@"Landscape Height: %f", screenBounds.size.height);
}
return screenBounds ;
}
Ответ 6
если вы хотите размер, зависящий от ориентации, и у вас есть представление, вы можете просто использовать:
view.bounds.size
Ответ 7
Я написал категорию для UIScreen
, которая работает на всех версиях iOS, поэтому вы можете использовать ее вот так:
[[UIScreen mainScreen] currentScreenSize]
.
@implementation UIScreen (ScreenSize)
- (CGSize)currentScreenSize {
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBounds.size;
if ( NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1 ) {
UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if ( UIInterfaceOrientationIsLandscape(interfaceOrientation) ) {
screenSize = CGSizeMake(screenSize.height, screenSize.width);
}
}
return screenSize;
}
@end
Ответ 8
Вот быстрый способ получить ориентационный размер экрана:
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
Ответ 9
float msWidth = [[UIScreen mainScreen] bounds].size.width*(IS_RETINA?2.0f:1.0f);
float msHeight = [[UIScreen mainScreen] bounds].size.height*(IS_RETINA?2.0f:1.0f);
if ( UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ) {
os->setWidth(MIN(msWidth, msHeight));
os->setHeight(MAX(msWidth, msHeight));
} else {
os->setWidth(MAX(msWidth, msHeight));
os->setHeight(MIN(msWidth, msHeight));
}
NSLog(@"screen_w %f", os->getWidth());
NSLog(@"screen_h %f", os->getHeight());
Ответ 10
Однако, на iOS 8.0.2:
+ (NSUInteger)currentWindowWidth
{
NSInteger width = 0;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
CGSize size = [UIScreen mainScreen].bounds.size;
// if (UIInterfaceOrientationIsLandscape(orientation)) {
// width = size.height;
// } else {
width = size.width;
// }
return width;
}