【问题标题】:how do I detect the iPhone orientation before rotating如何在旋转前检测 iPhone 方向
【发布时间】:2010-11-12 17:39:30
【问题描述】:

在我的程序中,我基于旋转来移动物体,但我并没有旋转整个视图。我正在使用:

  static UIDeviceOrientation previousOrientation = UIDeviceOrientationPortrait;

 - (void)applicationDidFinishLaunching:(UIApplication *)application {   
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
    [[NSNotificationCenter defaultCenter] addObserver:self
           selector:@selector(didRotate:)
           name:@"UIDeviceOrientationDidChangeNotification" object:nil];

}

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

    [self doRotationStuff:orientation: previousOrientation];
previousOrientation = orientation;

} 

只要在程序启动时设备方向是纵向的,但如果初始方向是横向或倒置,则此方法有效,因为 [self doRotationStuff] 会相对于与先前方向的差异进行更改。

有没有办法在启动时或在设备旋转之前检测方向?

【问题讨论】:

    标签: iphone objective-c cocoa-touch iphone-sdk-3.0


    【解决方案1】:

    这是在应用首次加载且 UIDeviceOrientation 设置为 UIDeviceOrientationUnknown 时获取方向的一种方法。您可以查看旋转视图的变换属性。

    if(toInterface == UIDeviceOrientationUnknown) {
        CGAffineTransform trans = navigationController.view.transform;
        if(trans.b == 1 && trans.c == -1)
            toInterface = UIDeviceOrientationLandscapeLeft;
        else if(trans.b == -1 && trans.c == 1)
            toInterface = UIDeviceOrientationLandscapeRight;
        else if(trans.a == -1 && trans.d == -1)
            toInterface = UIDeviceOrientationPortraitUpsideDown;
        else
            toInterface = UIDeviceOrientationPortrait;
    }
    

    【讨论】:

    • 这是金子!它将为您提供视图的方向。我将它与UIDeviceOrientationDidChangeNotification 一起使用来检测我之前的方向。
    【解决方案2】:

    如果您需要确定您指向的方向,请将此用于 UI 的方向。

    不是 100% 确定这是正确的,但我想不通:

    [[[UIApplication sharedApplication] statusBar] orientation]
    

    【讨论】:

      【解决方案3】:

      根据您的情况,更简单的选项可能是 UIViewController 类的 interfaceOrientation 属性。这在旋转之前是正确的。

      【讨论】:

      • 谢谢!我不知道 htat 字段存在 - 我使用的是 UIDevice 的方向,这不是很有帮助。
      • 这就是为什么 *** S.O Rocks ! *** ... 正在 Nugging Futz 试图解决 * cough * 简单的方向问题... 没有线索... 搜索出现了 delany 的答案。
      【解决方案4】:

      有关如何从加速器读数中获取设备方向的更完整示例,请参见here 由于该解决方案依赖于加速器读数,因此无法在模拟器上运行,因此您必须在设备上工作……仍在寻找适用于模拟器的解决方案。

      【讨论】:

        【解决方案5】:

        莫特,这些答案似乎有点牵强附会;我不明白为什么你不能为 UIViewController 类使用以下内置方法:

        -(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {}
        

        这个方法在旋转发生后被自动调用(而不是用 shouldAutorotateToInterfaceOrientation 只告诉你它即将发生)。方便地,变量“fromInterfaceOrientation”包含先前的方向。正如文档中所说,您可以假设视图的 interfaceOrientation 属性已设置为新方向,因此您有一种方法可以访问旧方向和新方向!

        如果我遗漏了什么,而您已经拒绝使用此方法,我深表歉意!在上述方法中免费提供变量时,您正在为“先前方向”创建和存储变量,这似乎很奇怪。

        希望有帮助!

        【讨论】:

        • 如果我打算旋转界面,我不想这样做。
        【解决方案6】:

        更新:

        因此,从评论讨论来看,您似乎不能依赖[UIDevice currentDevice].orientation,直到第一次真正改变方向。如果是这样,您可能可以通过获取原始加速度计读数来破解它。

        #define kUpdateFrequency 30  // Hz
        #define kUpdateCount 15 // So we init after half a second
        #define kFilteringFactor (1.0f / kUpdateCount)
        
        - (void)applicationDidFinishLaunching:(UIApplication *)app
        {
            [UIAccelerometer sharedAccelerometer].updateInterval = (1.0 / kUpdateFrequency);
            [UIAccelerometer sharedAccelerometer].delegate = self;
            accelerometerCounter = 0;
            ...
        }
        
        - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)accel
        {
            // Average out the first kUpdateCount readings
            // acceleration_[xyz] are ivars typed float
            acceleration_x = (float)accel.x * kFilteringFactor + acceleration_x * (1.0f - kFilteringFactor);
            acceleration_y = (float)accel.y * kFilteringFactor + acceleration_y * (1.0f - kFilteringFactor);
            acceleration_z = (float)accel.z * kFilteringFactor + acceleration_z * (1.0f - kFilteringFactor);
        
            accelerometerCounter++;
            if (accelerometerCounter == kUpdateCount)
            {
                [self initOrientation];
                [UIAccelerometer sharedAccelerometer].delegate = nil;
            }
        }
        
        - (void)initOrientation
        {
            // Figure out orientation from acceleration_[xyz] and set up your UI...
        }
        

        原始回复:

        [UIDevice currentDevice].orientationapplicationDidFinishLaunching: 期间是否返回正确的方向?如果是这样,您可以根据该方向设置初始 UI。

        如果该属性直到稍后才设置,您可以尝试使用performSelector:afterDelay: 在稍有延迟后初始化 UI。

        此代码示例来自 Kendall 在下面的回答,为了完整起见,在此处添加:

        [self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f];
        

        我不确定零秒延迟是否足够——这意味着getOriented 的代码将在第一次通过事件运行循环期间运行。您可能需要等待更长的时间才能在UIDevice 上注册加速度计读数。

        【讨论】:

        • 在 applicationDidFinishLaunching 期间,[UIDevice currentDevice].orientation 为 UIDeviceOrientationUnknown
        • 我不知道如何使用 performSelector:afterDelay。能给个代码示例吗?
        • 我试过你说的,但即使是 [self performSelector:@selector(getOriented) withObject:nil afterDelay:10.0f];没有任何影响
        • “没有任何效果”是什么意思?你的意思是延迟之后仍然是UIDeviceOrientationUnknown?您可能需要在启动期间致电 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications] 以确保方向正在更新。
        • 是的,我的意思是延迟后它仍然是 UIDeviceOrientationUnknown 。 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications] 正在被调用 - (void)applicationDidFinishLaunching:(UIApplication *)application { 你是否建议我需要提前激活它?
        【解决方案7】:

        作为对您的评论的回应,我认为我最好将代码放在这里而不是在评论中(尽管丹尼尔在这里确实值得称赞):

        在 applicationDidFinishLaunching 中:

        [self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f];
        

        那么你只需要调用的方法:

        - (void) getOriented 
        { 
           UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
           // save orientation somewhere
        }
        

        【讨论】:

        • 我试过你说的,但即使是 [self performSelector:@selector(getOriented) withObject:nil afterDelay:10.0f];没有任何影响
        • 十秒后调用时的方向是什么?似乎十秒钟后应该设置方向......或者那时,只需询问主视图控制器它的方向是什么。
        • 它是 UIDeviceOrientationUnknown
        猜你喜欢
        • 1970-01-01
        • 2015-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-03
        • 1970-01-01
        • 1970-01-01
        • 2010-11-03
        相关资源
        最近更新 更多