获取iPad的当前方向?

64
在给定的事件处理程序中(不是“shouldAutorotateToInterfaceOrientation”方法),我如何检测当前iPad的方向?我有一个文本字段,当键盘出现时必须向上动画显示在横向视图中,但不在纵向视图中,并希望知道我处于哪个方向以查看是否需要进行动画。
11个回答

133

屏幕方向信息不是很一致,有几种方法可以处理。如果在视图控制器中,您可以使用 interfaceOrientation 属性。从其他地方,您可以调用:

[[UIDevice currentDevice] orientation]

或者,您可以请求接收方向更改通知:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];

有些人也喜欢检查状态栏方向:

[UIApplication sharedApplication].statusBarOrientation

10
这非常有帮助。我之前使用[[UIDevice currentDevice] orientation],但当你把设备正面朝上时,无法确定界面朝向哪个方向。现在我使用[UIApplication sharedApplication].statusBarOrientation解决了这个问题。非常感谢。 - Daniel Wood
8
“[[UIDevice currentDevice] orientation] is faulty..It wasted my so much time..Thanks..” 可以翻译为:“[[UIDevice currentDevice] orientation] 有问题,浪费了我很多时间。谢谢。” - rohan-patel
4
注意:[[UIDevice currentDevice] orientation] 获取设备的旋转方向,而不是界面的旋转方向!如果用户锁定了设备的方向,则设备的方向和界面方向可能会非常不同。statusBarOrientation 返回一个界面方向,当用户锁定设备方向时,这是正确的方向。 - Tustin2121
2
不要使用[[UIDevice currentDevice] orientation]来获取设备方向:该属性的值是一个常量,表示设备当前的物理方向。这个值代表设备的物理方向,可能与你应用程序用户界面的当前方向不同。请参阅“UIDeviceOrientation”以了解可能的值的描述。 - Steven Fisher
实际上,setOrientation:确实有效 - 尽管它是非官方API。Objective C是一种动态语言,这是一件好事。 - Paul Lynch
显示剩余5条评论

35

我认为

[[UIDevice currentDevice] orientation];

这不是非常可靠的。 有时它可以正常工作,有时则不能...... 在我的应用程序中,我使用

[[UIApplication sharedApplication]statusBarOrientation]; 

它运行得很好!


3
"[UIDevice currentDevice] orientation"有问题,浪费了我很多时间。谢谢。" - rohan-patel
1
“可靠”不是问题。问题在于UIDevice的方向不适用于此目的。请参阅文档:http://developer.apple.com/library/ios/documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html#//apple_ref/occ/instp/UIDevice/orientation - Steven Fisher
1
在我的代码中,我需要知道两种不同的方向:界面方向和设备方向。当你拍照时,设备方向非常重要。 - Alex Stone
3
如果(UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication]statusBarOrientation])){//横屏}else{//竖屏} - Bharat

9

其中之一:

  • 检查活动视图控制器的 interfaceOrientation 属性。
  • [UIApplication sharedApplication].statusBarOrientation
  • [UIDevice currentDevice].orientation。(您可能需要调用 -beginGeneratingDeviceOrientationNotifications。)

8
我发现一个技巧来解决面朝上方向的问题!!!
将方向检查延迟到应用程序启动后,然后设置变量、视图大小等!!!
//CODE

- (void)viewDidLoad {

  [super viewDidLoad];

  //DELAY
  [NSTimer scheduledTimerWithTimeInterval:0.5 
                     target:self 
                     selector:@selector(delayedCheck) 
                     userInfo:nil 
                     repeats:NO];

}


-(void)delayedCheck{

  //DETERMINE ORIENTATION
  if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait ){
      FACING = @"PU";
  }
  if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown ){
      FACING = @"PD";
  }
  if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft ){
      FACING = @"LL";
  }
  if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight ){
      FACING = @"LR";
  } 
  //DETERMINE ORIENTATION

  //START
  [self setStuff];
  //START

}


-(void)setStuff{

  if( FACING == @"PU" ){
          //logic for Portrait
  }
  else
  if( FACING == @"PD" ){
          //logic for PortraitUpsideDown
  }
  else{ 
  if( FACING == @"LL"){
          //logic for LandscapeLeft
  }
  else
  if( FACING == @"LR" ){
          //logic for LandscapeRight
  }

}

//CODE

在“setStuff”函数中,您可以添加子视图、定位元素等内容,这些内容最初都取决于方向!!!

:D

-Chris Allinson


1
是的,但如果您的应用程序必须先绘制某些内容,因为否则屏幕会变黑呢? - zmippie
当一个应用程序启动时,它最初显示闪屏图像。在我制作的应用中,我通常让appDelegate视图控制器的.xib文件显示与闪屏相同的图像,然后让它淡出。我监听淡出完成的时间,然后添加子视图,这些子视图的alpha为0.0,然后将它们淡入。这是一种不错的效果(类似于视频游戏在你开始玩之前显示贡献公司)。我将所有的绘图逻辑都保留在这些添加的类中,因此当执行绘图代码时,应用程序已经完成启动并正在运行。 - Chris Allinson
异步地分派到主队列就足够了。事件仍将在方向处理后但屏幕更新之前触发。 - Steven Fisher

3
你可以通过两种方式实现这个目标:
1. 通过使用以下方法:
将下面这一行放置在-(void)viewDidLoad方法中:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceRotated:) name:UIDeviceOrientationDidChangeNotification object:nil];

然后将这个方法放在你的类里。
-(void)deviceRotated:(NSNotification*)notification
{

   UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
    {
        //Do your textField animation here
    }
}

以上方法将在设备旋转时检查方向。

2- 第二种方法是通过在-(void)viewDidLoad中插入以下通知来实现。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkRotation:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];

然后在你的类中添加以下方法:

-(void)checkRotation:(NSNotification*)notification
{
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
    {
         //Do your textField animation here
    }
}

以上方法将检查 iPad 或 iPhone 的状态栏方向,并根据其进行所需方向的动画。


2

为了确定横向还是纵向,有一个内置的函数:

UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
BOOL inLandscape = UIDeviceOrientationIsLandscape(orientation);

1

[UIApplication sharedApplication].statusBarOrientation 返回的是在 iPad 启动时处于横屏状态时返回竖屏,处于竖屏状态时返回横屏。


0

我尝试了上述许多方法,但似乎没有一种方法能够完全适用于我。

我的解决方案是在根视图控制器中创建一个名为orientation的iVar,类型为UIInterfaceOrientation。

- (void)viewDidLoad {

    [super viewDidLoad];
    orientation = self.interfaceOrientation; // this is accurate in iOS 6 at this point but not iOS 5; iOS 5 always returns portrait on app launch through viewDidLoad and viewWillAppear no matter which technique you use.
}


- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    return YES;
}

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

    orientation =  toInterfaceOrientation;

}

然后,任何需要检查方向的地方,您可以像这样做:

 if(UIInterfaceOrientationIsPortrait(orientation)){
    // portrait
  }else{
   // landscape
  }

可能还有更好的方法,但这似乎在大多数情况下都能正常工作(尽管iOS5除外),而且并不太难。请注意,iOS5始终以纵向视图启动iPad,然后发送willRotateTo-和didRotateFromInterfaceOrientation:消息给设备,因此该值仍然会短暂地不准确。


0

我不知道为什么,但每次我的应用程序启动时,前4个是正确的,但随后我得到相反的方向。我使用静态变量来计数,然后有一个BOOL来翻转我手动发送给子视图的方式。

因此,虽然我没有添加新的独立答案,但我建议使用上述方法并记住这一点。注意:我接收状态栏方向,因为它是在应用程序启动时唯一被调用且“足够正确”以帮助我移动东西。

使用此方法的主要问题是视图被懒加载。确保在响应其方向设置其位置之前调用包含和子视图的视图属性。感谢Apple在我们设置不存在的变量时不崩溃,迫使我们记住它们会破坏OO并强制我们也这样做...呃,如此优雅的系统却如此脆弱!说真的,我喜欢Native,但它只是不好,鼓励了糟糕的OO设计。这不是我们的错,只是提醒您的调整大小函数可能正在工作,但Apple的方式要求您通过使用而不是创建和初始化来加载视图


0
在您的视图控制器中,获取self.interfaceOrientation的只读值(界面的当前方向)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接