如何在iOS上检测设备的方向?


72

我对如何在iOS上检测设备方向有疑问。我不需要接收更改通知,仅需要接收当前方向。这似乎是一个相当简单的问题,但我无法将其包裹住。以下是我到目前为止所做的事情:

UIDevice *myDevice = [UIDevice currentDevice] ;
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation deviceOrientation = myDevice.orientation;
BOOL isCurrentlyLandscapeView = UIDeviceOrientationIsLandscape(deviceOrientation);
[myDevice endGeneratingDeviceOrientationNotifications];

在我看来,这应该可行。我使设备能够接收设备方向通知,然后询问设备所处的方向,但随后却无法正常工作,我也不知道为什么。



Answers:


120

确实是旧线程,但没有真正的解决方案。

我遇到了同样的问题,但是发现获取UIDeviceOrientation并不总是一致的,因此可以使用以下方法:

UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;

if(orientation == 0) //Default orientation 
    //UI is in Default (Portrait) -- this is really a just a failsafe. 
else if(orientation == UIInterfaceOrientationPortrait)
    //Do something if the orientation is in Portrait
else if(orientation == UIInterfaceOrientationLandscapeLeft)
    // Do something if Left
else if(orientation == UIInterfaceOrientationLandscapeRight)
    //Do something if right

5
如果可以的话,这是最正确的答案。这样,您只需检查此属性即可随时获取界面方向。请注意,状态栏是否隐藏并不重要,无论如何该属性都会被更新!
ktolis 2012年

3
如果您挑剔并且选择不依赖故障保险,请不要忘记UIInterfaceOrientationPortraitUpsideDown
Ark

这对我有用,除了根本不检测肖像。我必须检测它是对还是左,然后如果都不对,则将其作为纵向处理。
Marcel Marino

4
如果应用程序的方向仅限于纵向模式或横向模式,则此功能将无效。
Salman Khakwani 2014年

就我而言,它不起作用,它始终返回纵向。我将p列表更改为接受多个方向。有人知道为什么吗?
ZijunLost

76

如果UIViewController:

if (UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
    // 
}

如果UIView:

if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
    //
}

UIDevice.h:

#define UIDeviceOrientationIsPortrait(orientation)  ((orientation) == UIDeviceOrientationPortrait || (orientation) == UIDeviceOrientationPortraitUpsideDown)
#define UIDeviceOrientationIsLandscape(orientation) ((orientation) == UIDeviceOrientationLandscapeLeft || (orientation) == UIDeviceOrientationLandscapeRight)

更新时间

将此代码添加到xxx-Prefix.pch中,然后可以在任何地方使用它:

// check device orientation
#define dDeviceOrientation [[UIDevice currentDevice] orientation]
#define isPortrait  UIDeviceOrientationIsPortrait(dDeviceOrientation)
#define isLandscape UIDeviceOrientationIsLandscape(dDeviceOrientation)
#define isFaceUp    dDeviceOrientation == UIDeviceOrientationFaceUp   ? YES : NO
#define isFaceDown  dDeviceOrientation == UIDeviceOrientationFaceDown ? YES : NO

用法:

if (isLandscape) { NSLog(@"Landscape"); }

1
这是一个很好的答案。我对文档进行了仔细检查-不仅是一个很好的答案,从正确性的角度来看,这是一个正确的答案。值得标记为已检查。
Dumoko

1
这是我在设备方向确定说明中想要的。谢谢你,TONy。W
Morkrom 2013年

有趣的是,在我的iPad模拟器上似乎只能正确触发“ isLandscape”(无论其他所有返回否)。尚未有机会在我的真实硬件上进行测试……但是,我喜欢您的方法。谢谢。
BonanzaDriver

1
UIViewController::interfaceOrientation返回UIInterfaceOrientation,而UIDeviceOrientationIsLandscape接受UIDeviceOrientation。这可能在今天有效,但不兼容向前。
2014年

1
'interfaceOrientation'已弃用:iOS 8.0中首次弃用
Bill Chan

22

对于您首先要寻找的内容,如果方向发生变化,则必须获取通知!您可以在viewDidLoad中设置此内容,例如

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];

以及每当设备的方向发生变化时,就会调用OrientationDidChange,您可以在其中根据方向进行任何操作

-(void)OrientationDidChange:(NSNotification*)notification
{
    UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];

    if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight)
    {
    }
    else if(Orientation==UIDeviceOrientationPortrait)
    {
    }
}

1
这实际上对我来说是完美的,因为我仅在一个ViewController中需要此信息,其余的应用程序不应更改其方向。所以谢谢!
CarmenA 2015年

22

如果要直接从加速度计获取设备方向,请使用[[UIDevice currentDevice] orientation]。但是,如果您需要应用程序的当前方向(接口方向),请使用[[UIApplication sharedApplication] statusBarOrientation]


9

UIViewController具有interfaceOrientation可以访问以查找视图控制器当前方向的属性。

至于您的示例,那应该可行。当您说它不起作用时,您是什么意思?与预期相比,它能给您带来什么结果?


1
我正在iOS模拟器中对其进行调试,无论设备的朝向如何,它始终会返回NO。当我在其上设置一个断点时,我发现deviceOrientation = myDevice.orientation的输出始终为UIDeviceOrientationUnknown,因此它看起来好像无法正确跟踪方向。
JusmanX 2011年

8

在Swift 3.0中

获取设备方向。

/* return current device orientation.
   This will return UIDeviceOrientationUnknown unless device orientation notifications are being generated. 
*/
UIDevice.current.orientation

从您的应用程序获取设备方向

UIApplication.shared.statusBarOrientation

2
“'statusBarOrientation'在iOS 13.0中已被弃用:改为使用窗口场景的interfaceOrientation属性。” 这是参考 stackoverflow.com/questions/25796545/…–
Egel,

4

“ UIDeviceOrientation”不满足要求,因为当将UIViewcontroller方向固定为特定方向时,您不会获得与设备方向相关的信息,因此正确的做法是使用“ UIInterfaceOrientation”

您可以使用“ self.interfaceOrientation”从UIViewController获得方向,但是在分解我们的代码时,可能需要在视图控制器(自定义视图,类别…)之外进行这种测试。可以使用rootviewController在控制器外部的任何位置访问信息:

if (UIInterfaceOrientationIsLandscape(view.window.rootViewController.interfaceOrientation)) {
}

2

有一种方法可以通过使用CoreMotion的数据来实现是否启用方向锁定。这是代码:

#import <CoreMotion/CoreMotion.h> 

    CMMotionManager *cm=[[CMMotionManager alloc] init];
    cm.deviceMotionUpdateInterval=0.2f;
    [cm startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
                            withHandler:^(CMDeviceMotion *data, NSError *error) {

                            if(fabs(data.gravity.x)>fabs(data.gravity.y)){
                                    NSLog(@"LANSCAPE");
                                if(data.gravity.x>=0){
                                    NSLog(@"LEFT");
                                }
                                else{
                                    NSLog(@"RIGHT");
                                }

                        }
                        else{
                                NSLog(@"PORTRAIT");
                                if(data.gravity.y>=0){
                                    NSLog(@"DOWN");
                                }
                                else{

                                    NSLog(@"UP");
                                }

                            }

}];


1

以下是一些Swift变量,可简化检测过程:

let LANDSCAPE_RIGHT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight
let LANDSCAPE_LEFT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft
let LANDSCAPE: Bool = LANDSCAPE_LEFT || LANDSCAPE_RIGHT
let PORTRAIT_NORMAL: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.Portrait
let PORTRAIT_REVERSE: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.PortraitUpsideDown
let PORTRAIT: Bool = PORTRAIT_REVERSE || PORTRAIT_NORMAL

0

我目前的做法是:

+ (BOOL)isPortrait {
    let window = UIApplication.sharedApplication.delegate.window;
    if(window.rootViewController) {
        let orientation =
        window.rootViewController.interfaceOrientation;
        return UIInterfaceOrientationIsPortrait(orientation);
    } else {
        let orientation =
        UIApplication.sharedApplication.statusBarOrientation;
        return UIInterfaceOrientationIsPortrait(orientation);
    }
}

如果由于某种原因没有rootViewController仍然无法安全地进行statusBarOrientation ...


0

最快的最佳可靠方式:

public extension UIScreen {

    public class var isPortrait: Bool {
        UIApplication.shared.delegate?.window??.rootViewController?.interfaceOrientation.isPortrait ??
                UIApplication.shared.statusBarOrientation.isPortrait
    }

    public class var isLandscape: Bool { !isPortrait }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.