Created
December 6, 2021 02:32
-
-
Save jzxchiang1/bd7e906038eb9a2c57857b5f1a0d6a3f to your computer and use it in GitHub Desktop.
How to get accurate device orientation on iOS even with rotate lock turned on
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m | |
index 6117764..de9eaec 100644 | |
--- a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m | |
+++ b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/Orientation.m | |
@@ -8,6 +8,7 @@ | |
#import "Orientation.h" | |
+#import "RCTSensorOrientationChecker.h" | |
@implementation Orientation | |
@@ -15,6 +16,7 @@ @implementation Orientation | |
#if (!TARGET_OS_TV) | |
UIInterfaceOrientation _lastOrientation; | |
UIInterfaceOrientation _lastDeviceOrientation; | |
+ RCTSensorOrientationChecker * _sensorOrientationChecker; | |
#endif | |
BOOL _isLocking; | |
} | |
@@ -41,6 +43,7 @@ - (instancetype)init | |
_lastOrientation = [UIApplication sharedApplication].statusBarOrientation;; | |
_lastDeviceOrientation = (UIInterfaceOrientation) [UIDevice currentDevice].orientation; | |
_isLocking = NO; | |
+ _sensorOrientationChecker = [RCTSensorOrientationChecker new]; | |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil]; | |
[self addListener:@"orientationDidChange"]; | |
@@ -166,9 +169,10 @@ - (void)lockToOrientation:(UIInterfaceOrientation) newOrientation usingMask:(UII | |
{ | |
#if (!TARGET_OS_TV) | |
[[NSOperationQueue mainQueue] addOperationWithBlock:^ { | |
- UIInterfaceOrientation deviceOrientation = (UIInterfaceOrientation) [UIDevice currentDevice].orientation; | |
- NSString *orientationStr = [self getOrientationStr:deviceOrientation]; | |
- callback(@[orientationStr]); | |
+ [_sensorOrientationChecker getDeviceOrientationWithBlock:^(UIInterfaceOrientation deviceOrientation) { | |
+ NSString *orientationStr = [self getOrientationStr:deviceOrientation]; | |
+ callback(@[orientationStr]); | |
+ }]; | |
}]; | |
#endif | |
} | |
diff --git a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/RCTSensorOrientationChecker.h b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/RCTSensorOrientationChecker.h | |
new file mode 100644 | |
index 0000000..15dc9e4 | |
--- /dev/null | |
+++ b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/RCTSensorOrientationChecker.h | |
@@ -0,0 +1,21 @@ | |
+// | |
+// RCTSensorOrientationChecker.h | |
+// RCTCamera | |
+// | |
+// Created by Radu Popovici on 24/03/16. | |
+// | |
+// | |
+ | |
+#import <UIKit/UIKit.h> | |
+#import <AVFoundation/AVFoundation.h> | |
+ | |
+typedef void (^RCTSensorCallback) (UIInterfaceOrientation orientation); | |
+ | |
+@interface RCTSensorOrientationChecker : NSObject | |
+ | |
+@property (assign, nonatomic) UIInterfaceOrientation orientation; | |
+ | |
+- (void)getDeviceOrientationWithBlock:(RCTSensorCallback)callback; | |
+- (AVCaptureVideoOrientation)convertToAVCaptureVideoOrientation:(UIInterfaceOrientation)orientation; | |
+ | |
+@end | |
diff --git a/node_modules/react-native-orientation-locker/iOS/RCTOrientation/RCTSensorOrientationChecker.m b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/RCTSensorOrientationChecker.m | |
new file mode 100644 | |
index 0000000..fc0e457 | |
--- /dev/null | |
+++ b/node_modules/react-native-orientation-locker/iOS/RCTOrientation/RCTSensorOrientationChecker.m | |
@@ -0,0 +1,105 @@ | |
+// | |
+// RCTSensorOrientationChecker.m | |
+// RCTCamera | |
+// | |
+// Created by Radu Popovici on 24/03/16. | |
+// | |
+// | |
+ | |
+#import "RCTSensorOrientationChecker.h" | |
+#import <CoreMotion/CoreMotion.h> | |
+ | |
+ | |
+@interface RCTSensorOrientationChecker () | |
+ | |
+@property (strong, nonatomic) CMMotionManager * motionManager; | |
+@property (strong, nonatomic) RCTSensorCallback orientationCallback; | |
+ | |
+@end | |
+ | |
+@implementation RCTSensorOrientationChecker | |
+ | |
+- (instancetype)init | |
+{ | |
+ self = [super init]; | |
+ if (self) { | |
+ // Initialization code | |
+ self.motionManager = [[CMMotionManager alloc] init]; | |
+ self.motionManager.accelerometerUpdateInterval = 0.2; | |
+ self.motionManager.gyroUpdateInterval = 0.2; | |
+ self.orientationCallback = nil; | |
+ } | |
+ return self; | |
+} | |
+ | |
+- (void)dealloc | |
+{ | |
+ [self pause]; | |
+} | |
+ | |
+- (void)resume | |
+{ | |
+ __weak __typeof(self) weakSelf = self; | |
+ [self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue new] | |
+ withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { | |
+ if (!error) { | |
+ self.orientation = [weakSelf getOrientationBy:accelerometerData.acceleration]; | |
+ } | |
+ if (self.orientationCallback) { | |
+ self.orientationCallback(self.orientation); | |
+ } | |
+ }]; | |
+} | |
+ | |
+- (void)pause | |
+{ | |
+ [self.motionManager stopAccelerometerUpdates]; | |
+} | |
+ | |
+- (void)getDeviceOrientationWithBlock:(RCTSensorCallback)callback | |
+{ | |
+ __weak __typeof(self) weakSelf = self; | |
+ self.orientationCallback = ^(UIInterfaceOrientation orientation) { | |
+ if (callback) { | |
+ callback(orientation); | |
+ } | |
+ weakSelf.orientationCallback = nil; | |
+ [weakSelf pause]; | |
+ }; | |
+ [self resume]; | |
+} | |
+ | |
+- (UIInterfaceOrientation)getOrientationBy:(CMAcceleration)acceleration | |
+{ | |
+ if(acceleration.x >= 0.75) { | |
+ return UIInterfaceOrientationLandscapeLeft; | |
+ } | |
+ if(acceleration.x <= -0.75) { | |
+ return UIInterfaceOrientationLandscapeRight; | |
+ } | |
+ if(acceleration.y <= -0.75) { | |
+ return UIInterfaceOrientationPortrait; | |
+ } | |
+ if(acceleration.y >= 0.75) { | |
+ return UIInterfaceOrientationPortraitUpsideDown; | |
+ } | |
+ return [[UIApplication sharedApplication] statusBarOrientation]; | |
+} | |
+ | |
+- (AVCaptureVideoOrientation)convertToAVCaptureVideoOrientation:(UIInterfaceOrientation)orientation | |
+{ | |
+ switch (orientation) { | |
+ case UIInterfaceOrientationPortrait: | |
+ return AVCaptureVideoOrientationPortrait; | |
+ case UIInterfaceOrientationPortraitUpsideDown: | |
+ return AVCaptureVideoOrientationPortraitUpsideDown; | |
+ case UIInterfaceOrientationLandscapeLeft: | |
+ return AVCaptureVideoOrientationLandscapeLeft; | |
+ case UIInterfaceOrientationLandscapeRight: | |
+ return AVCaptureVideoOrientationLandscapeRight; | |
+ default: | |
+ return 0; // unknown | |
+ } | |
+} | |
+ | |
+@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment