Knowing the interface orientation of an iPad at ap

2019-08-05 16:41发布

问题:

I am trying to figure out my iPad's orientation at start up on a flat table.

I always says it's starting in portrait mode, which it isn't true.

I have used the code sampled here to detect the orientation at start up.

It so happens that when my device is face up on a flat surface it claims it is in portrait mode. However the status bar is visually in landscape mode.

Is there a way around this?

I am using iOS 5 and Xcode 4.3.

EDIT: More details

Here is my update orientation method:

- (void)updateOrientation {

    UIInterfaceOrientation iOrientation = self.interfaceOrientation;//[[UIApplication sharedApplication] statusBarOrientation];
    UIDeviceOrientation dOrientation = [UIDevice currentDevice].orientation;

    bool landscape;

    if (dOrientation == UIDeviceOrientationUnknown || dOrientation == UIDeviceOrientationFaceUp || dOrientation == UIDeviceOrientationFaceDown) {
        // If the device is laying down, use the UIInterfaceOrientation based on the status bar.
        landscape = UIInterfaceOrientationIsLandscape(iOrientation);
    } else {
        // If the device is not laying down, use UIDeviceOrientation.
        landscape = UIDeviceOrientationIsLandscape(dOrientation);

        // There's a bug in iOS!!!! http://openradar.appspot.com/7216046
        // So values needs to be reversed for landscape!
        if (dOrientation == UIDeviceOrientationLandscapeLeft) iOrientation = UIInterfaceOrientationLandscapeRight;
        else if (dOrientation == UIDeviceOrientationLandscapeRight) iOrientation = UIInterfaceOrientationLandscapeLeft;

        else if (dOrientation == UIDeviceOrientationPortrait) iOrientation = UIInterfaceOrientationPortrait;
        else if (dOrientation == UIDeviceOrientationPortraitUpsideDown) iOrientation = UIInterfaceOrientationPortraitUpsideDown;
    }

    whiteView.hidden = NO;
    splashScreen.hidden = NO;
    if (landscape) {
        splashScreen.image = [UIImage imageNamed:@"Default-Landscape~ipad"];
    } else {
        splashScreen.image = [UIImage imageNamed:@"Default-Portrait~ipad"];
    }

    splashScreen.contentMode = UIViewContentModeScaleToFill;
    [self.view bringSubviewToFront:whiteView];
    [self.view bringSubviewToFront:splashScreen];

    // Set the status bar to the right spot just in case
    [[UIApplication sharedApplication] setStatusBarOrientation:iOrientation];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (splashScreen){
        [self updateOrientation];
        [UIView animateWithDuration:0.5 delay:1 options:UIViewAnimationOptionCurveEaseInOut 
                         animations:^{
                             splashScreen.alpha = 0;
                         } 
                         completion:^(BOOL success){
                             [splashScreen removeFromSuperview];
                             splashScreen = nil;
                         }];

        [UIView animateWithDuration:0.5 delay:1.5 options:UIViewAnimationOptionCurveEaseInOut 
                         animations:^{
                             whiteView.alpha = 0;
                         } 
                         completion:^(BOOL success){
                             [whiteView removeFromSuperview];
                             whiteView = nil;
                         }];
}

The problem is noticeable when I start my app in a flat surface in landscape mode I see the wrong image being loaded up for the spashscreen.

回答1:

Use [[UIApplication sharedApplication] statusBarOrientation] instead of [UIDevice currentDevice] orientation].

There's a difference between device orientation and user interface orientation (and some elaboration can be found on this related question). Many apps might have a user interface designed to only work certain ways even though the device is pointed another way.



回答2:

I'm experiencing the same problem, and I have not found any good solution.

It seems that [[UIApplication sharedApplication] statusBarOrientation] always return 1 before application:didFinishLaunchingWithOptions: has finish, and only if your device is face up (maybe face down too, i have not tried)

I finally done this :

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    // For the cases where device is not face up.
    if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
        [self doTheJobInPortrait];
    else
        [self doTheJobInLandscape];

    // For the cases where device is face up
    [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(hackForFaceUpLandscapeDevices) userInfo:nil repeats:NO];
}

-(void)hackForFaceUpLandscapeDevices {
    if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
        [self doTheJobInPortrait];
    else
        [self doTheJobInLandscape];
}

Of course, the job will be done two times, and in face up lanscape mode there will be a short moment where your interface will be in portrait...

If someone find a better solution, I would be glad to know it.



回答3:

That's why there is often used a 'blank view' at startup, that just initializes your app. When the first view is laoded, you can easily check for the correct device-orientation.

After this you load your device-orientation-specific View. So you have:

One ViewController One Blank View Two Views with content (one landscape, one portrait)

I think, e. g. Safari Mobile does it that way.