React Native 实践系列:《React-Native-Orientaion 屏幕翻转实战》
前言
之前利用 React-Native-Orientaion 完成屏幕反转实战,也踩了一些坑在这里分享一下。
安装和集成
github 所在地址: react-native-orientation
安装命令
npm install react-native-orientation --save
缺陷
只能监听屏幕设备的反转,不能细颗粒到组件层面的翻转,如果需要做到组件层面的翻转,推荐使用 https:// github.com/wonday/react -native-orientation-locker
做兼容
在使用中发现不少坑,比如我在Android 端使用以下办法无效,
Orientation.addSpecificOrientationListener
注意:在iOS 端如果启用方向传感器的话,回调是不会被调用的,而Android 是一直都调用,所以Android的监听我不用这个。
所以,我使用
Dimensions.addEventListener("change",cb) // Android 端监听设备翻转
但这个方法也不是高性能的办法, 根据官方的说法,不仅仅手动翻转设备时会触发,
而且在当前应用的屏幕尺寸发生变化时,比如应用从全屏模式切换到非全屏模式也会触发,还有用户在设置中修改了设备的显示模式也会触发,所以不是很高效。
iOS端在 反复旋转之后偶尔会故障
需要手动设置支持的方向
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
翻转之后需要Android解锁
从api的介绍来看,关于lockToxx 中 lock的理解,在iOS和 Android 是不一样的,
iOS是 旋转 ,而Android 是 锁定, 这就意味着如果开启自动旋转时,旋转一个方向成功后,还需要解锁传感器,不然无法发生自动旋转。
所以在Android lockToxx 之后,需要根据读取Android 的系统变量,
android.provider.Settings.System.ACCELEROMETER_ROTATION
完整的获取Android
用户是否自动旋转标志
的方法应该如下:
// 这是我在 react-native-orientation 后续自己添加的方法
@ReactMethod
public void getAutoRotateState(Callback callback) {
final ContentResolver resolver = getReactApplicationContext().getContentResolver();
boolean rotateLock = android.provider.Settings.System.getInt(
resolver,
android.provider.Settings.System.ACCELEROMETER_ROTATION, 0) == 1;
callback.invoke(rotateLock);
}
Orientation.getAutoRotateState(autoRotate => {
if (autoRotate === false) {
// fix: 锁住时不发生自动旋转
Orientation.lockToPortrait();
if(autoRotate){
// 是否支持自动旋转,若是,则调用unlockAllOrientations (针对Android)
Orientation.unlockAllOrientations();
对于API的理解
addSpecificOrientationListener
addSpecificOrientationListener((specificOrientation) => {});
为了提升性能还可以 添加防抖措施 :
addSpecificOrientationListener(debounce(_direction => {},500));
addSpecificOrientationListener 是iOS端监听屏幕翻转的核心方法,
为什么不使用 addOrientationListener 方法,因为它并不能区分是 左水平 还是 右水平,而 addSpecificOrientationListener 可以。
-
LANDSCAPE-LEFT
-
LANDSCAPE-RIGHT
-
PORTRAIT
-
PORTRAITUPSIDEDOWN
-
UNKNOWN
lockToPortrait(或者lockToxxx)
旋转(锁定)某个位置,此外还有 lockToLandScape
在项目中还需要配合 LANDSCAPE-LEFT 和 LANDSCAPE-RIGHT 。
Android 端在开启传感器时反复旋转
unlockAllOrientations 是开启传感器时,可以自动开启旋转屏幕。
反复横跳,有的时候并不能够旋转到指定的位置,所以需要用Android原生监听来规定
,细分什么情况下需要旋转。
private final void startOrientationChangeListener() {
if (mOrientationListener == null) {
mOrientationListener = new OrientationEventListener(context) {
@Override
public void onOrientationChanged(int rotation) {
Log.d("onOrientationChanged", rotation+""+island);
int triggerAngle = 45;
// 超过45度旋转 ,包括 左边 或者 右边
if (((rotation > triggerAngle) &&
(rotation < 180 - triggerAngle)) ||
((rotation > 180 + triggerAngle) && (rotation < 360 - triggerAngle))) {//landscape
if (!island) {
island = true;
// 方向传感器是否打开
if (isScreenchange(context)) {
final Activity activity = getCurrentActivity();
if (activity == null) {
return;
int orientation = activity.getRequestedOrientation();
if (orientation != ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
// 切换为传感器的方向
Log.d("unlockAllOrientations", rotation+"");
unlockAllOrientations();
} else {
island = false;
mOrientationListener.enable();
}
但是记得在页面onPagePause 时消除掉这个 listener
// OrientationModule.java
private final void closeOrientationChangeListener() {
if (mOrientationListener != null) {
mOrientationListener.disable();
}
// .js
const pagePause = ()=>{
if (Platform.OS === "android") {