SCREEN_ORIENTATION_LANDSCAPE вверх ногами – почему?

Я использую следующий код для установки блокировки ориентации в соответствии с предпочтениями пользователя:

 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).

Почему это так и как мне подойти к этой проблеме, чтобы исправить это?

Мой первоначальный запрос показал, что существует довольно много возможностей, кроме два обычных (portrait, landscape), включая reverseLandscape, но моя догадка подсказывает мне, что эта проблема может быть зависит от устройства, поэтому, используя его, я могу решить проблему только для своего телефона, но не для всех других устройств.

Есть ли способ заставить правильную ориентацию landscape (при переключении с sensor) на всех устройствах?

Чтобы сделать это более ясным и легким для воспроизведения, вот шаги, которые демонстрируют проблему:

  1. Начните с телефона, повернутого вправо (по часовой стрелке), в разблокированном режиме (SCREEN_ORIENTATION_SENSOR) с правильным отображением LANDSCAPE на экране (!),
  2. Затем вызовите doLock(true)
  3. Вместо блокировки экрана на LANDSCAPE в текущем (правильном) ландшафтном виде он фиксируется в перевернутом ландшафтном виде. то есть то же самое, но перевернуть вертикально (y становится -y).

person an00b    schedule 21.08.2012    source источник


Ответы (4)


То, что вы описываете, является не ошибкой, а скорее ожидаемым поведением Android 2.2 или ниже.

@forgivegod предоставил теоретически правильный подход, за исключением того, что для Android 2.2 или ниже значения screenOrientation.reverseLandscape и screenOrientation.reversePortrait не распознаются, даже если они подделаны (как это делает код @forgivegod).

Бьюсь об заклад, вы видите эту проблему, когда вы поворачиваете телефон по часовой стрелке (вращение = 3), но не против часовой стрелки (вращение = 1).

Попробуйте с Android 2.3 или выше и посмотрите, что произойдет.

person ateiob    schedule 21.08.2012
comment
ОМГ вы правы! Когда я поворачиваю телефон влево, а затем фиксирую его в setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);, он работает нормально. Когда я поворачиваю телефон вправо и делаю то же самое, он, конечно, остается в SCREEN_ORIENTATION_LANDSCAPE. Когда я поворачиваю телефон вправо, а затем фиксирую его в положении setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);, он фактически делает портрет!. Похоже, во Фройо его игнорируют. Я попробовал то же самое с Gingerbread, и проблема не возникла. - person an00b; 21.08.2012
comment
@an00b Рад, что смог помочь. Также обратите внимание, что activity.getWindowManager().getDefaultDisplay().getOrientation() фиксируется в onCreate(). То есть в onResume() вы все равно получите значение, полученное в onCreate(), даже если вы повернули телефон непосредственно перед onResume(). - person ateiob; 22.08.2012

Попробуйте следующее, чтобы отключить и включить ориентацию с помощью кода (это будет работать на уровне 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);
}
person petey    schedule 21.08.2012
comment
+1 за подробный ответ. Однако в вашем коде обнаружена та же самая проблема, которую я описал выше. Я все еще озадачен. - person an00b; 21.08.2012
comment
из любопытства, что происходит, когда вы меняете свой doLock(true) на просто activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); это все еще обратный пейзаж? - person petey; 21.08.2012
comment
Вы должны измениться на альбомную, когда ориентация портретная, и наоборот. - person Wojtek; 21.09.2017

Простой и функциональный>

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

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

  </application>
person Kamuy    schedule 07.11.2014

попробуйте с универсальной альбомной ориентацией

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;
      }
person Community    schedule 21.08.2012