这是我编写的用于处理锁定和解锁屏幕方向的类。我从切换按钮的checkedChangedListener 调用toggleScreenOrientationLock(this, prefs, isChecked),从onCreate() 调用restoreScreenLock(this, prefs)。在这两种情况下,this 是您的活动,prefs 是 SharedPrefences 对象,用于保存有关锁状态的信息。
代码中复杂的部分是getScreenOrientation() 函数which I stole from and cleaned up from here。我将尝试解释其工作原理背后的逻辑。
当我们用setRequestedOrienation()设置设备的方向时,我们需要知道设备是横向模式还是纵向模式,我们需要知道它是反向(旋转180度)。
使用getResources().getConfiguration().orientation 将回答我们处于哪个方向的问题。如果我们可以考虑设备的旋转,我们可以判断它是否旋转了 180 度。不幸的是,根据设备,ROTATE_0 可能是纵向或横向的。手机通常将 ROTATE_0 映射为纵向,而平板电脑则映射为横向。
所以这里使用的解决方案是使用屏幕尺寸来确定它是横向还是纵向。如果屏幕的宽度大于高度,那么我们推断设备处于横向,反之亦然。然后我们可以考虑旋转来判断方向是否反转。
例如,如果屏幕的宽度大于高度,那么我们就知道我们处于横向。如果旋转是 0 或 180(在代码的逻辑中,这等于 !isRotatedOrthogonally),那么我们知道 0 是 LANDSCAPE,而 180 是 REVERSE_LANDSCAPE。
It has been noted elsewhere 这不适用于所有设备,因为 90 或 270 是反向方向是特定于设备的。但这仍然可能是您要做的最好的事情;在最坏的情况下,当您锁定某个方向时,它会旋转 180 度,如果尝试以任何其他方式锁定屏幕,可能会发生这种情况。
public class ScreenLocker {
final private static String ROTATION_LOCKED_KEY = "LockedOrientationVal";
final private static String ROTATION_IS_LOCKED_KEY = "IsRotationLocked";
final private static String ROTATION_SAVED_KEY = "SavedOrientationVal";
public static int getScreenOrientation(Activity activity) {
final Display display = activity.getWindowManager().getDefaultDisplay();
final int rotation = display.getRotation();
Point size = new Point();
display.getSize(size);
final boolean isWiderThanTall = size.x > size.y;
final boolean isRotatedOrthogonally = (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
int orientation;
if (isRotatedOrthogonally) {
if (isWiderThanTall)
orientation = (rotation == Surface.ROTATION_90) ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
else
orientation = (rotation == Surface.ROTATION_90) ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; // normal and reversed switched intended
}
else {
if (isWiderThanTall)
orientation = (rotation == Surface.ROTATION_0) ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
else
orientation = (rotation == Surface.ROTATION_0) ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}
return orientation;
}
public static void toggleScreenOrientationLock(Activity activity,SharedPreferences prefs, boolean lock) {
if(lock)
lockScreenOrientation(activity, prefs);
else
unlockScreenOrientation(activity, prefs);
}
// call this from your activity's onCreate() or onResume()
public static boolean restoreScreenLock(Activity activity, SharedPreferences prefs) {
final boolean isLocked = prefs.getBoolean(ROTATION_IS_LOCKED_KEY, false);
final int previousLockedOrientation = prefs.getInt(ROTATION_LOCKED_KEY, -999);
if(isLocked && previousLockedOrientation != -999) {
prefs.edit().putInt(ROTATION_SAVED_KEY, activity.getRequestedOrientation()).apply();
activity.setRequestedOrientation(previousLockedOrientation);
return true;
}
return false;
}
private static void lockScreenOrientation(Activity activity, SharedPreferences prefs) {
final int currentOrientation = activity.getRequestedOrientation();
final int lockOrientation = getScreenOrientation(activity);
// checking isCurrentlyLocked prevents the ROTATION_LOCKED_KEY and ROTATION_SAVED_KEY
// becoming identical, which results in the screen not being able to be unlocked.
final boolean isCurrentlyLocked = prefs.getBoolean(ROTATION_IS_LOCKED_KEY, false);
if(!isCurrentlyLocked) {
activity.setRequestedOrientation(lockOrientation);
prefs.edit()
.putInt(ROTATION_SAVED_KEY, currentOrientation)
.putInt(ROTATION_LOCKED_KEY, lockOrientation)
.putBoolean(ROTATION_IS_LOCKED_KEY, true)
.apply();
}
}
private static void unlockScreenOrientation(Activity activity, SharedPreferences prefs) {
final int savedOrientation = prefs.getInt(ROTATION_SAVED_KEY, activity.getRequestedOrientation());
activity.setRequestedOrientation(savedOrientation);
prefs.edit().putBoolean(ROTATION_IS_LOCKED_KEY, false).apply();
}
}