Question

I have a deadline soon and I have very annoying bug in front of me and no ideas, how to fix it. The problem is, that sometimes device doesn't know what it's orientation is before it has been rotated and so it messes up frames in conditional statements:

 if (orient == UIInterfaceOrientationPortrait || orient == 0){ 
  r = CGRectMake(0.0, 0.0, 320.0, 480.0);
        // draw stuff
    } else {
  r = CGRectMake(0.0, 0.0, 480.0, 320.0);
        // draw stuff
    }

This bug can be easily reproduced if I keep device on the table or in hands (horizontal position) and run my application, it draws landscape-like rectangles in portrait type screen.

My questions are: can I somehow get the right orientation in this kind of situation? Too bad it can not be reproduced in simulator, so I'm not sure if the code I pasted is responsible for this bug, but that is the place where I fix view frames according to orientation. Maybe there's another (proper) way to do that? And maybe I can force application to be in portrait mode until rotation event will be fired?

Was it helpful?

Solution

I don't think it is a bug. When the iPhone is sitting on the table all the gravity is meassured along the Z axis. To determine device orientation x-y axis are used, but no acceleration is measured alongside of them in your scenario.

EDIT: Further explanations:

This image shows how the Axis are oriented on the iPhone: alt text http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIAcceleration_Class/Art/device_axes.jpg

So when you have the iPhone lying on the back, an acceleration of -1g is applied on the z axis. To receive the measured accelerations simply register a delegate implementing UIAccelerometerDelegate with the UIAccelerometershared instance. See the AccelerometerGraph sample how this is done.

To determine if the iphone sits on the table do something like this:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
    {

    // lowPass filter first

    // now choose orientation
      if (fabs([acceleration z]) >= 0.9) // sitting on the table: choose new mode or lock current mode
      if (fabs([acceleration y]) >= 0.9) // probably portrait mode
      if (fabs([acceleration x]) >= 0.9) // probably landscape mode

    }

The accelerometer precision is 18mG = 0.018G so take that into account. Also you need to isolate yourself from the effects of instant movement changes, a simple LowPass filter fits this bill perfectly. The AccelerometerGraph sample shows how to implement such a filter.

Also choose a very low updateInterval if you don't need a lot of precision, 30Hz should be okay for your purposes.

OTHER TIPS

The sensor which determines the device's orientation is neither infallible nor intelligent. If you set the phone down on the table and then walk around it, how is it supposed to know that it's upside down?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top