iOS device orientation disregarding orientation lock

后端 未结 10 1269
天涯浪人
天涯浪人 2020-11-29 01:59

I want to query the orientation the iPhone is currently in. Using

[UIDevice currentDevice].orientation

works as long as the device isn\'t

10条回答
  •  离开以前
    2020-11-29 02:48

    Handling all 6 orientations

    Though we don't often care about FaceUp / FaceDown orientations, they're still important.

    Taking them into account leads to a much more appropriate sensitivity for orientation changes, while leaving them out can lead to metastability & hysteresis.

    Here's how I handled it -

    - (void)startMonitoring
    {
        [self.motionManager startAccelerometerUpdatesToQueue:self.opQueue withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
    
            if (error != nil)
            {
                NSLog(@"Accelerometer error: %@", error);
            }
            else
            {
                float const threshold = 40.0;
    
                BOOL (^isNearValue) (float value1, float value2) = ^BOOL(float value1, float value2)
                {
                    return fabsf(value1 - value2) < threshold;
                };
    
                BOOL (^isNearValueABS) (float value1, float value2) = ^BOOL(float value1, float value2)
                {
                    return isNearValue(fabsf(value1), fabsf(value2));
                };
    
                float yxAtan = (atan2(accelerometerData.acceleration.y, accelerometerData.acceleration.x)) * 180 / M_PI;
                float zyAtan = (atan2(accelerometerData.acceleration.z, accelerometerData.acceleration.y)) * 180 / M_PI;
                float zxAtan = (atan2(accelerometerData.acceleration.z, accelerometerData.acceleration.x)) * 180 / M_PI;
    
                UIDeviceOrientation orientation = self.orientation;
    
                if (isNearValue(-90.0, yxAtan) && isNearValueABS(180.0, zyAtan))
                {
                    orientation = UIDeviceOrientationPortrait;
                }
                else if (isNearValueABS(180.0, yxAtan) && isNearValueABS(180.0, zxAtan))
                {
                    orientation = UIDeviceOrientationLandscapeLeft;
                }
                else if (isNearValueABS(0.0, yxAtan) && isNearValueABS(0.0, zxAtan))
                {
                    orientation = UIDeviceOrientationLandscapeRight;
                }
                else if (isNearValue(90.0, yxAtan) && isNearValueABS(0.0, zyAtan))
                {
                    orientation = UIDeviceOrientationPortraitUpsideDown;
                }
                else if (isNearValue(-90.0, zyAtan) && isNearValue(-90.0, zxAtan))
                {
                    orientation = UIDeviceOrientationFaceUp;
                }
                else if (isNearValue(90.0, zyAtan) && isNearValue(90.0, zxAtan))
                {
                    orientation = UIDeviceOrientationFaceDown;
                }
    
                if (self.orientation != orientation)
                {
                    dispatch_async(dispatch_get_main_queue(), ^{
    
                        [self orientationDidChange:orientation];
                    });
                }
            }
        }];
    }
    

    Additionally, I've added a threshold value of 40.0 (instead of 45.0). This makes changes less sensitive, preventing hysteresis at inflection points.

    If you only want to react to changes of the main 4 orientations, just do this

    if (UIDeviceOrientationIsPortrait(orientation) || UIDeviceOrientationIsLandscape(orientation))
    {
         // Do something
    }
    

提交回复
热议问题