翻译:iPhone的加速计和设备的方向

#前言:

  • 利用iPhone的加速计来检测设备旋转的方向。翻译的有什么不对还请指点一二。谢谢

原文地址:
iPhone accelerometer and device orientation

所以今天苹果发布了iPhone OS 3.0的beta版本。这是第5个beta版我们越来越接近最终的3.0版。我们不会看见很多的API的改变,因为只有很少的改变和新增的功能。在二月份我发布了一个蛮长的关于:如何在不旋转整个应用的情况下旋转图片的解决方案,在那里我使用了shouldAutorotateToInterfaceOrientation。最近我写了一篇博文关于shouldAutorotateToInterfaceOrientation的改变 这个改变在我看来是严重影响了我的程序的重要功能。作为承诺,这里你可以使用accelerometer(加速计)替换掉shouldAutorotateToInterfaceOrientation;
更新
Kyle非常友好的发布了关于你如何监听shouldAutorotateToInterfaceOrientation事件的一个简单的解决方案。我已经使用它的方案更新了之前发布的博文(或者你可以看他下面的评论):shouldAutorotateToInterfaceOrientation的重大改变
这个应用叫做DeviceOrientation并且这是一个概念性的佐证,不是一个完全替代shouldAutorotateToInterfaceOrientation.非常不幸的是在模拟器上是无法使用加速计的,你需要将项目运行在你的iPhone上来进行测试。这里是一个简陋的剪辑,我使用iMac的iSight的记录,它比想象中的去记录坐在设备后面更难,屏幕本身增加了一个讨厌的炫光的iPhone。但至少这很短,enjoy:
(由于po主的电脑显示不了视频,各位可以去原文查看)

#注意数学和代码的头部!
为了计算来自加速计的角度,你需要使用atan2函数,这里是维基百科的简短解释,这样子我就可以不用解释什么是atan2.

In trigonometry, the two-argument function atan2 is a variation of the arctangent function. For any real arguments x and y not both equal to zero, atan2(y, x) is the angle in radians between the positive x-axis of a plane and the point given by the coordinates (x, y) on it. The angle is positive for counter-clockwise angles (upper half-plane, y > 0), and negative for clockwise angles (lower half-plane, y < 0).

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    // Get the current device angle
    float xx = -[acceleration x];
    float yy = [acceleration y];
    float angle = atan2(yy, xx);
}

我做了些努力来创造一个有希望的容易理解的可视化的角度和设备真实方向的关系。如果你握着你的手机在你的面前当你看着这张图片然后旋转你的手机并和这张图片比较这是很容易找到对应关系的。
So many iPhones on a single picture, awesome!
从图片中我们很明显可以知道设备的每一个方向之间的角度差是1.5,然后每一个方向的位移时大于0.75的。下面的这些代码改变了label text的方向,但只有当设备的方向从一个转为另一个时发生。

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
// Get the current device angle
    float xx = -[acceleration x];
    float yy = [acceleration y];
    float angle = atan2(yy, xx);

    // Add 1.5 to the angle to keep the label constantly horizontal to the viewer.
    [interfaceOrientationLabel setTransform:CGAffineTransformMakeRotation(angle+1.5)];

    // Read my blog for more details on the angles. It should be obvious that you
    // could fire a custom shouldAutorotateToInterfaceOrientation-event here.
    if(angle >= -2.25 && angle <= -0.75)
    {
        if(deviceOrientation != UIInterfaceOrientationPortrait)
        {
            deviceOrientation = UIInterfaceOrientationPortrait;
            [interfaceOrientationLabel setText:@"UIInterfaceOrientationPortrait"];
        }
    }
    else if(angle >= -0.75 && angle <= 0.75)
    {
        if(deviceOrientation != UIInterfaceOrientationLandscapeRight)
        {
            deviceOrientation = UIInterfaceOrientationLandscapeRight;
            [interfaceOrientationLabel setText:@"UIInterfaceOrientationLandscapeRight"];
        }
    }
    else if(angle >= 0.75 && angle <= 2.25)
    {
        if(deviceOrientation != UIInterfaceOrientationPortraitUpsideDown)
        {
            deviceOrientation = UIInterfaceOrientationPortraitUpsideDown;
            [interfaceOrientationLabel setText:@"UIInterfaceOrientationPortraitUpsideDown"];
        }
    }
    else if(angle <= -2.25 || angle >= 2.25)
    {
        if(deviceOrientation != UIInterfaceOrientationLandscapeLeft)
        {
            deviceOrientation = UIInterfaceOrientationLandscapeLeft;
            [interfaceOrientationLabel setText:@"UIInterfaceOrientationLandscapeLeft"];
        }
    }
}

如果你想要替换shouldAutorotateToInterfaceOrientation你可以使用这里的代码,然后在替换掉label文字的改变这里触发你的事件。
源码下载:
正如我在上面写的(防止你直接跳到代码这里看),这个应用你必须运行在真机赏,模拟器时没有加速器的。它可以在模拟器上云霄,但不如你所愿的那样子触发加速计的功能。这个代码时免费供你使用在任何地方。所有在这个blog上的代码都是免费供您使用的,即使在某些文件上的注释说的不一样。
完整的文件

#相关文章

Zerlz wechat
扫码关注一个很懒的程序员!
Winter is coming, give me a penny!