화면의 방향에 따른 높이와 너비를 얻는 방법은 무엇입니까?


96

내 응용 프로그램의 현재 높이와 너비를 프로그래밍 방식으로 결정하려고합니다. 나는 이것을 사용한다 :

CGRect screenRect = [[UIScreen mainScreen] bounds];

그러나 이것은 장치가 세로 방향이든 가로 방향이든 상관없이 너비 320과 높이 480을 산출합니다. 메인 화면 의 현재 너비와 높이 (즉, 장치 방향에 따라 다름)를 어떻게 확인할 수 있습니까?

답변:


164

같은 UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)것을 사용하여 방향을 결정한 다음 그에 따라 치수를 사용할 수 있습니다 .

그러나 UIViewController에서와 같이 방향이 변경되는 동안

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
                                 duration:(NSTimeInterval)duration

toInterfaceOrientationUIApplication의 statusBarOrientation은 아직 변경되지 않았기 때문에 ( will이벤트 핸들러 내부에 있기 때문에) 여전히 이전 방향을 가리 키므로 전달 된 방향을 사용하십시오 .

요약

이와 관련된 여러 게시물이 있지만 각각 다음을 수행해야 함을 나타내는 것 같습니다.

  1. [[UIScreen mainScreen] bounds]크기를 얻으려면,
  2. 현재 어떤 방향인지 확인하고
  3. 상태 표시 줄 높이 고려 (표시된 경우)

연결

작업 코드

나는 보통 여기까지 가지 않지만 당신은 내 관심을 불러 일으켰습니다. 다음 코드가 트릭을 수행해야합니다. UIApplication에 카테고리를 작성했습니다. UIViewController의 .NET Framework에서 호출하는 지정된 방향으로 currentSize 또는 크기를 가져 오는 클래스 메서드를 추가했습니다 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을 빼야했습니다.

도움이 되었기를 바랍니다. :디

다른 생각들

UIWindow의 rootViewController속성을 확인 하여 치수를 가져올 수 있습니다. 나는 과거에 이것을 보았고 회전 변환이 있다고보고하는 것을 제외하고 세로 및 가로 모두에서 동일한 치수를 유사하게보고합니다.

(gdb) po [[[[UIApplication sharedApplication] keyWindow] rootViewController]보기]

<UILayoutContainerView : 0xf7296f0; 프레임 = (0 0; 320480); 변형 = [0, -1, 1, 0, 0, 0]; 자동 크기 조정 = W + H; 레이어 = <CALayer : 0xf729b80 >>

(gdb) po [[[[UIApplication sharedApplication] keyWindow] rootViewController]보기]

<UILayoutContainerView : 0xf7296f0; 프레임 = (0 0; 320480); 자동 크기 조정 = W + H; 레이어 = <CALayer : 0xf729b80 >>

앱이 어떻게 작동하는지 확실하지 않지만 어떤 종류의 탐색 컨트롤러를 사용하지 않는 경우 기본보기 아래에 부모의 최대 높이 / 너비가 있고 부모와 함께 확장 / 축소되는 UIView가있을 수 있습니다. 그런 다음 할 수 [[[[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] subviews] objectAtIndex:0] frame]있습니다.. 한 줄에서 꽤 강렬 해 보이지만 아이디어를 얻습니다.

그러나 ... 요약 아래에서 위의 3 단계를 수행하는 것이 좋습니다. UIWindows를 엉망으로 만들면 UIAlertView가 UIAlertView가 만든 새 UIWindow를 가리 키도록 UIApplication의 키창을 변경하는 것과 같은 이상한 것들을 발견하게 될 것입니다. 누가 알았 겠어? 나는 keyWindow에 의존하는 버그를 발견하고 그것이 그렇게 변경되었음을 발견 한 후에했다!


5
이것은 내가 이와 같은 것을 결정하기 위해 내 자신의 코드를 해킹해야한다고 믿는 데 어려움을 겪고있는 초보적인 작업처럼 보입니다.
MusiGenesis

2
다른 솔루션을 시도하고 작동하면 다시 게시하겠습니다. 이 사이트는 빨리 대답하지 않으면 전혀 대답하지 않을 수도 있습니다. 하하 ... : DI 내 대답이 적어도 도움이되기를 바랍니다. 다시 한 번, 다른 것을 빨리 시도해 보겠습니다.
Sam

1
큰! :-) (BTW, 하나는 하나의 관심은 감정을 상하게있다)
바 모스

1
(UIScreen에서) applicationFrame대신 사용 bounds하면 상태 표시 줄 높이를 뺄 필요가 없습니다.
aopsfan 2013 년

2
stackoverflow.com/questions/24150359/...는 mainScreen().bounds.size 이후 아이폰 OS 8에서 좌우 방향이되었다
제럴드

39

이것은 내 솔루션 코드입니다!이 메소드는 NSObject 클래스의 Categroy에 추가하거나 Top 사용자 정의 UIViewController 클래스를 정의하고 다른 모든 UIViewController가 상속하도록 할 수 있습니다.

-(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 이후 UIScreen의 경계 속성에 대한 Apple 문서는 다음 과 같이 말합니다.

토론

이 사각형은 현재 좌표 공간에 지정되며 장치에 적용되는 모든 인터페이스 회전을 고려합니다. 따라서이 속성의 값은 기기가 세로 방향과 가로 방향 사이에서 회전 할 때 변경 될 수 있습니다.

따라서 호환성을 고려하여 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 ;
}

내 대답과 거의 동일하지만 세로가 거꾸로 된 경우에만 놓친 것입니다. 이것은 당신이 그 방향을 지원하는 경우에만 중요합니다.
Robert Wagstaff 2013

2
@Monjer는 GET 요청을 수행하지 않는 메소드의 이름을 지정해서는 안되며, 앞에 단어 get이 붙습니다. currentScreenBoundsDependOnOrientation은 메소드의 더 나은 이름입니다
bogen

1
@ Hakonbogen.yes는 "peroperty"선언이 자동으로 setter / getter 메서드를 생성하고 이로 인해 명명 충돌이 발생할 수 있으며 objc의 명명 규칙에 위배 될 수 있기 때문에 귀하가 옳을 수 있습니다. 귀하의 조언에 감사드립니다.
monjer 2013 년

애플이 마침내 로테이션 코드가 완전히 엉망이라는 것을 암묵적으로 인정하고 방금 현재 방향에서 망할 치수가 무엇인지 알려주기 시작했다는 것은 좋은 일입니다. 버전 8까지 거기에 도달하는 것이 너무 나쁩니다.
MusiGenesis 2014 년

30

다음은 편리한 매크로입니다.

#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)

14

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

이것은 받아 들여진 대답이어야합니다. 현대적이고 최신입니다.
SarpErdag

이 답변은 iOS 8 이상에서 사용하십시오.
iPhoneDeveloper

10

iOS 8부터는 화면 경계가 현재 방향에 대해 올바르게 반환됩니다. 즉, 가로 방향의 iPad [UIScreen mainScreen] .bounds는 iOS <= 7에서는 768을, iOS 8에서는 1024를 반환합니다.

다음은 출시 된 모든 버전에서 올바른 높이와 너비를 반환합니다.

-(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 ;
}

8

방향에 따른 크기를 원하고 뷰가있는 경우 다음을 사용할 수 있습니다.

view.bounds.size

큰! KISS 솔루션 =이 유지 그것은 간단하고 바보
bsorrentino

3
KISS는 "단순하고 어리석게 유지"를 의미하지 않습니다. LOL! "단순하고 멍청 해!"라는 뜻입니다. :-)
Erik van der Neut 2014

또한이 답변은 뷰가 정확히 전체 화면으로 알려진 경우에만 작동합니다. 그러나 그것이 사실이라면 아마도 OP가 게시 한 원래 문제가 없을 것입니다.
에릭 반 Neut 데르

5

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

1
이것은 나에게 가장 깨끗한 대답처럼 보입니다. 찬성.
에릭 반 Neut 데르

5

다음은 방향에 따른 화면 크기를 얻는 신속한 방법입니다.

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


0
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());

0

그러나 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;
}

0

크기를 조정할보기에 대해-> setNeedsDisplay ()를 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.