【问题标题】:How Do I detect the orientation of the device on iOS?如何在 iOS 上检测设备的方向?
【发布时间】:2011-04-05 23:12:13
【问题描述】:

我有一个关于如何在 iOS 上检测设备方向的问题。我不需要接收更改通知,只需要接收当前方向本身。这似乎是一个相当简单的问题,但我一直无法理解它。以下是我到目前为止所做的:

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

在我看来,这应该可行。我让设备能够接收设备方向通知,然后询问它的方向,但是它不起作用,我不知道为什么。

【问题讨论】:

标签: ios objective-c orientation uidevice


【解决方案1】:

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

我遇到了同样的问题,但发现获取 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

【讨论】:

  • 如果可以的话,这是最正确的答案。这样,您只需检查此属性即可随时获取界面方向。注意,不管状态栏是否隐藏,属性都会更新!
  • 如果您很挑剔并选择不依赖故障保护,请不要忘记UIInterfaceOrientationPortraitUpsideDown
  • 这对我有用,除了它根本没有检测到肖像。我必须检测它是右还是左,如果两者都不是,则将其作为纵向处理。
  • 如果应用程序的方向仅限于纵向模式或横向模式,这将不起作用。
  • 在我的情况下它不起作用,它总是返回肖像。我更改了 p-list 以接受多个方向。有谁知道为什么?
【解决方案2】:

如果 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"); }

【讨论】:

  • 这是一个非常好的答案。我已经仔细检查了文档-更多的是,这是一个很好的答案,从正确性的角度来看,它是正确的。值得标记为已检查。
  • 这就是我在设备方向确定解释中想要的全部内容。谢谢你,托尼。 W
  • 有趣的是,只有 'isLandscape' 似乎在我的 iPad 模拟器上正确触发(无论如何,所有其他人都返回 NO)。还没有机会在我的真实硬件上进行测试……但是,我喜欢你的方法。谢谢。
  • UIViewController::interfaceOrientation 返回UIInterfaceOrientation,而UIDeviceOrientationIsLandscape 接受UIDeviceOrientation。这在今天可能有效,但它不向前兼容。
  • 'interfaceOrientation' 已弃用:在 iOS 8.0 中首次弃用
【解决方案3】:

对于您首先要查找的内容,如果方向更改,您必须获得通知! 您可以在 viewDidLoad 中设置 This Thing 之类的

[[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)
    {
    }
}

【讨论】:

  • 这实际上对我来说非常有效,因为我只需要一个 ViewController 中的信息,应用程序的其余部分不应该改变它的方向。所以谢谢你!
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    UIViewController 有一个interfaceOrientation 属性,您可以访问该属性以找出视图控制器的当前方向。

    至于你的例子,这应该有效。当你说它不起作用时,你是什么意思?与您的预期相比,它给您带来了什么结果?

    【讨论】:

    • 我在 iOS 模拟器中调试它,无论设备的方向如何,它总是返回 NO。当我在它处设置断点时,我发现 deviceOrientation = myDevice.orientation 的输出总是 UIDeviceOrientationUnknown,所以它看起来并没有正确跟踪方向。
    【解决方案6】:

    在 Swift 3.0 中

    获取设备方向。

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

    从您的应用获取设备方向

    UIApplication.shared.statusBarOrientation
    

    【讨论】:

    【解决方案7】:

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

    您可以使用 "self.interfaceOrientation" 从 UIViewController 获取方向,但是当您分解我们的代码时,您可能需要在视图控制器之外进行这种测试,(自定义视图,一个类别...),因此您仍然可以使用 rootviewController 访问控制器之外的任何地方的信息:

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

    【讨论】:

      【解决方案8】:

      无论方向锁定是否启用,都有一种方法可以通过使用来自 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");
                                      }
      
                                  }
      
      }];
      

      【讨论】:

        【解决方案9】:

        您是否为设备方向解锁了硬件锁?我的 iPad 1 边缘有一个。

        【讨论】:

        【解决方案10】:

        这里有一些 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
        

        【讨论】:

          【解决方案11】:

          我目前的做法:

          + (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...

          【讨论】:

            【解决方案12】:

            最可靠的 swift 方法:

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

            【讨论】:

              【解决方案13】:

              这是我使用 Combine 的解决方案,它很容易与 SwiftUI 或常规 Swift Object 一起使用。单例对象(静态实例)比这种真正全局对象的“环境”要好。

              // Singleton object to keep the interface orientation (and any other global state)
              class SceneContext: ObservableObject {
                  @Published var interfaceOrientation = UIInterfaceOrientation.portrait
                  static let shared = SceneContext()
              }
              
              class SceneDelegate: UIResponder, UIWindowSceneDelegate {
                  ...
                  func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) {
                      SceneContext.shared.interfaceOrientation = windowScene.interfaceOrientation
                  }
              }
              
                  // if you want to execute some code whenever the orientation changes in SwiftUI
                  someView {
                      ....
                  }
                  .onReceive(SceneContext.shared.$interfaceOrientation) { (orientation) in
                      // do something with the new orientation
                  }
              
                  // if you want to execute some code whenever the orientation changes in a regular Swift object
                  let pub = SceneContext.shared.$interfaceOrientation.sink(receiveValue: { (orientation) in
                          // do something with the new orientation
                          ...
                      }) 
              
              

              【讨论】:

                【解决方案14】:

                使用此功能。

                    func deviceOrientation() -> String! {
                    let device = UIDevice.current
                    if device.isGeneratingDeviceOrientationNotifications {
                            device.beginGeneratingDeviceOrientationNotifications()
                            var deviceOrientation: String
                            let deviceOrientationRaw = device.orientation.rawValue
                            switch deviceOrientationRaw {
                            case 1:
                                deviceOrientation = "Portrait"
                            case 2:
                                deviceOrientation = "Upside Down"
                            case 3:
                                deviceOrientation = "Landscape Right"
                            case 4:
                                deviceOrientation = "Landscape Left"
                            case 5:
                                deviceOrientation = "Camera Facing Down"
                            case 6:
                                deviceOrientation = "Camera Facing Up"
                            default:
                                deviceOrientation = "Unknown"
                            }
                            return deviceOrientation
                        } else {
                            return nil
                        }
                    }
                

                【讨论】:

                  猜你喜欢
                  • 2015-12-11
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-09
                  • 1970-01-01
                  • 2013-11-11
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多