談談iOS中的屏幕方向


眾所周知,iOS中提供了[UIDevice currentDevice].orientation與[UIApplication sharedApplication].statusBarOrientation這兩種方式來獲取設備的屏幕方向。

其中UIDeviceOrientation包括以下幾種枚舉值

typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
    UIDeviceOrientationUnknown,
    UIDeviceOrientationPortrait,            // Device oriented vertically, home button on the bottom
    UIDeviceOrientationPortraitUpsideDown,  // Device oriented vertically, home button on the top
    UIDeviceOrientationLandscapeLeft,       // Device oriented horizontally, home button on the right
    UIDeviceOrientationLandscapeRight,      // Device oriented horizontally, home button on the left
    UIDeviceOrientationFaceUp,              // Device oriented flat, face up
    UIDeviceOrientationFaceDown             // Device oriented flat, face down
} __TVOS_PROHIBITED;

其中UIInterfaceOrientation包括以下幾種枚舉值

typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
    UIInterfaceOrientationUnknown            = UIDeviceOrientationUnknown,
    UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
    UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
    UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
    UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
} __TVOS_PROHIBITED;

可以看出UIInterfaceOrientation本質其實就是UIDeviceOrientation,但是這不是重點,說說我最近遇到的坑吧。

首先外部是一個tableview的列表頁,cell里面有視頻可以播,需求是列表頁不需要重力感應,也就說一直保持垂直方向,但是cell中的視頻點開后需要全屏,這個視頻是要有重力感應的。

這時會出現一個問題,如果我手機保持橫屏,第一次進入視頻,視頻並不會改變方向,並且UIDeviceOrientation打印出來為UIDeviceOrientationPortrait,因為我在視頻的controller里才beginGeneratingDeviceOrientationNotifications,[UIDevice currentDevice].orientation在沒有遇到方向改變的時候,他是不會更新狀態的!!!所以就造成了與實際方向不符的情況。而父頁面,也就是列表頁的UIInterfaceOrientation始終垂直,所以[UIApplication sharedApplication].statusBarOrientation也是用不了的,腫么辦!!!

於是乎,別人推薦了CMMotionManager來對方向進行判斷,CMMotionManager是從屬於Core Motion框架,利用iPhone上的重力加速計芯片來捕捉手機的各種加速值。

代碼如下:

- (void)initializeMotionManager{
    motionManager = [[CMMotionManager alloc] init];
    motionManager.accelerometerUpdateInterval = .2;
    motionManager.gyroUpdateInterval = .2;

    [motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
               withHandler:^(CMAccelerometerData  *accelerometerData, NSError *error) {
                      if (!error) {
                                [self outputAccelertionData:accelerometerData.acceleration];
                      }
                      else{
                                NSLog(@"%@", error);
                      }
    }];
}
- (void)outputAccelertionData:(CMAcceleration)acceleration{
    UIInterfaceOrientation orientationNew;

    if (acceleration.x >= 0.75) {
        orientationNew = UIInterfaceOrientationLandscapeLeft;
    }
    else if (acceleration.x <= -0.75) {
        orientationNew = UIInterfaceOrientationLandscapeRight;
    }
    else if (acceleration.y <= -0.75) {
        orientationNew = UIInterfaceOrientationPortrait;
    }
    else if (acceleration.y >= 0.75) {
        orientationNew = UIInterfaceOrientationPortraitUpsideDown;
    }
    else {
        // Consider same as last time
        return;
    }

    if (orientationNew == orientationLast)
        return;

    orientationLast = orientationNew;
}

這樣就可以實時的獲得當前設備的方向啦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM