SCREEN_ORIENTATION_LANDSCAPE倒置 - 为什么?

13

我正在使用以下代码根据用户偏好设置方向锁定:

 private void doLock(boolean locked) {
     if (locked) {
       int o = getResources().getConfiguration().orientation;
       if (o == Configuration.ORIENTATION_LANDSCAPE)
         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);       
       else if (o == Configuration.ORIENTATION_PORTRAIT)
         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);       
     } 
     else {
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
     }
 }

除了处于解锁模式(SCREEN_ORIENTATION_SENSOR)且屏幕正确地显示为LANDSCAPE外,它可以工作!然后调用doLock(true),但是...

屏幕锁定时,不会锁定到其当前(正确的)横向视图LANDSCAPE,而会锁定到上下颠倒的横向视图。即完全相同但垂直翻转(y变为-y)。

为什么会这样,我该如何解决这个问题?

我的最初查询显示,除了常见的两种(portraitlandscape)之外,还有很多可能性,包括reverseLandscape,但我的直觉告诉我,这个问题可能是设备相关的,因此使用它可能只会为我的手机修复问题,而不是所有其他设备。

有一种方法可以在所有设备中强制正确的landscape方向(从sensor切换)吗?

为了使这更清晰、更易于复现,这里是展示问题的步骤:

  1. 从右边(顺时针)旋转手机,在解锁模式下(SCREEN_ORIENTATION_SENSOR),屏幕正确显示为LANDSCAPE
  2. 然后调用doLock(true)
  3. 屏幕不会锁定到其当前(正确的)横向视图LANDSCAPE,而会锁定到一个上下颠倒的横向视图。即完全相同但垂直翻转(y变为-y)。
4个回答

9

尝试使用以下代码来禁用和启用屏幕方向(适用于API级别7及以上):

public static void disableRotation(Activity activity) {
    final int orientation = activity.getResources().getConfiguration().orientation;
    final int rotation = activity.getWindowManager().getDefaultDisplay()
            .getOrientation();

    // Copied from Android docs, since we don't have these values in Froyo
    // 2.2
    int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
    int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;

    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO) {
        SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    }

    if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    } else if (rotation == Surface.ROTATION_180
            || rotation == Surface.ROTATION_270) {
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        }
    }
}

public static void enableRotation(Activity activity) {
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

非常感谢您提供详细的答案。然而,您的代码展示了我上述描述的完全相同的问题。我仍然感到困惑。 - an00b
2
只是出于好奇,当您将doLock(true)更改为"activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);"时会发生什么?它仍然是反向横屏吗? - petey
当屏幕方向为竖屏时,应该切换到横屏;反之亦然。 - Wojtek

8

简单而实用>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

    <activity
        android:screenOrientation="sensorLandscape"
    </activity>

  </application>

6
你所描述的不是一个错误,而是Android 2.2或更低版本的预期行为。
@forgivegod提供了一种理论上正确的方法,但是对于Android 2.2或更低版本,即使伪造(就像@forgivegod的代码一样),也无法识别screenOrientation.reverseLandscape和screenOrientation.reversePortrait值。
我敢打赌,当你将手机顺时针旋转(旋转=3)时,你会看到这个问题,但逆时针旋转(旋转=1)时却不会出现。
尝试使用Android 2.3或更高版本,看看会发生什么。

1
哦我的天啊,你是对的!当我将手机向左旋转,然后锁定为setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);时,它可以正常工作。 当我将手机向右旋转并执行相同的操作时,它当然仍处于SCREEN_ORIENTATION_LANDSCAPE模式。但是当我将手机向右旋转并锁定为setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);时,它实际上会变成纵向模式!看起来在Froyo版本中会被忽略。我尝试用Gingerbread版本进行了完全相同的操作,它没有出现这个问题。 - an00b
@an00b 很高兴我能帮到你。还要注意的是,activity.getWindowManager().getDefaultDisplay().getOrientation()onCreate() 中被固定。也就是说,在 onResume() 中,即使在 onResume() 之前旋转了手机,仍然会得到在 onCreate() 中检索到的值。 - ateiob

2
尝试使用通用横向方向。
private static final int ORIENTATION_90 = 1;
private static final int ORIENTATION_0 = 0;
private static final int ORIENTATION_180 = 2;
private static final int ORIENTATION_270 = 3;

switch (orientation)
    {
      default:
      case ORIENTATION_0: // Portrait
        //dostuff
        break;
      case ORIENTATION_90: // Landscape left
        //do stuff
        break;
      case ORIENTATION_180: // Upside down.
        //do stuff
        break;
      case ORIENTATION_270: // Landscape right
        //do stuff
        break;
      }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接