Блокировка ориентации экрана - PullRequest
34 голосов
/ 06 июля 2011

Есть ли надежный способ блокировки ориентации экрана на всех устройствах Android?Приведенный ниже код работает для моего Nexus S и других телефонов, но по какой-то причине ROTATION_90 соответствует SCREEN_ORIENTATION_REVERSE_PORTRAIT в Xoom.

Есть ли способ надежно отобразить поворот на ориентацию?

private void lockScreenOrientation() {
    if (!mScreenOrientationLocked) {
        final int orientation = getResources().getConfiguration().orientation;
        final int rotation = getWindowManager().getDefaultDisplay().getOrientation();

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

        mScreenOrientationLocked = true;
    }
}

private void unlockScreenOrientation() {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    mScreenOrientationLocked = false;
}

РЕДАКТИРОВАТЬ: Этот код предназначен для получения текущей ориентации и ее блокировки.Ориентация временно блокируется, а затем передается пользователю.

Ответы [ 8 ]

34 голосов
/ 09 декабря 2011

Вот мое решение, оно работает на телефонах и планшетах в любом Android SDK.

switch (getResources().getConfiguration().orientation){
        case Configuration.ORIENTATION_PORTRAIT:
            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                int rotation = getWindowManager().getDefaultDisplay().getRotation();
                if(rotation == android.view.Surface.ROTATION_90|| rotation == android.view.Surface.ROTATION_180){
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                } else {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                }
            }   
        break;

        case Configuration.ORIENTATION_LANDSCAPE:
            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            } else {
                int rotation = getWindowManager().getDefaultDisplay().getRotation();
                if(rotation == android.view.Surface.ROTATION_0 || rotation == android.view.Surface.ROTATION_90){
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                } else {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                }
            }
        break;
    }
18 голосов
/ 07 января 2012

Я слегка изменил ответы diyism, чтобы компенсировать тот факт, что вы не можете использовать режимы reverse_landscape и reverse_portrait до версии 2.3

private 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);
        }
    }
}

private static void enableRotation(Activity activity)
{
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
6 голосов
/ 19 апреля 2012

для временная блокировка экрана вы можете легко использовать:

//developing for android tablets **<uses-sdk android:minSdkVersion="12" />**
//works perfectly... **WATCH OUT**: look portrait to reverse-portrait on api level 13 :)

currentActivity.setRequestedOrientation(currentActivity.getResources().getConfiguration().orientation);

//to re-enable sensor, just do:

currentActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

использовал его для временной блокировки экрана во время показа диалога и выполнения важной фоновой работы.

убедитесь, что currentActivity действительна в момент, когда вы пытаетесь получить к нему доступ, иначе он не будет работать:)

удачи:)

3 голосов
/ 24 сентября 2013
// Works on all devices. The other solution only works on 1/2 of the devices.
// Lock orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
lockOrientation(rotation, Surface.ROTATION_270);
// Ensure that the rotation hasn't changed
if (getWindowManager().getDefaultDisplay().getRotation() != rotation) {
    lockOrientation(rotation, Surface.ROTATION_90);
}
// ...
private void lockOrientation(int originalRotation, int naturalOppositeRotation) {
    int orientation = getResources().getConfiguration().orientation;
    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
        // Are we reverse?
        if (originalRotation == Surface.ROTATION_0 || originalRotation == naturalOppositeRotation) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            setReversePortrait();
        }
    } else {
        // Are we reverse?
        if (originalRotation == Surface.ROTATION_0 || originalRotation == naturalOppositeRotation) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else {
            setReverseLandscape();
        }
    }
}

@SuppressLint("InlinedApi") 
private void setReversePortrait() {
    if (Build.VERSION.SDK_INT >= 9) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
}

@SuppressLint("InlinedApi") 
private void setReverseLandscape() {
    if (Build.VERSION.SDK_INT >= 9) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}
2 голосов
/ 21 декабря 2013

Это решение основано только на других.Это другой способ решения проблемы, с которой сейчас сталкиваются: на некоторых устройствах ландшафт равен ROTATION_90, а на некоторых (несколько) - ROTATION_270.Когда я попробовал что-то вроде решения inv8enmentnow на Kindle Fire HD 7 ", он заставил экран вращаться вверх ногами, а затем сразу назад. Я не видел других идей, кроме как жестко кодировать, какие устройства считают ландшафт равным 270, так что вотжестко запрограммированное решение:

public static void unlockOrientation() {

    activity.setRequestedOrientation(
        ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

public static void lockOrientation() {

    if (Build.VERSION.SDK_INT < 18) {
        activity.setRequestedOrientation(getOrientation());
    } else {
        activity.setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_LOCKED);
    }
}

private static int getOrientation() {

    int port = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    int revP = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
    int land = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    int revL = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
    if (Build.VERSION.SDK_INT < 9) {
        revL = land;
        revP = port;
    } else if (isLandscape270()) {
        land = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
        revL = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    }

    Display display = activity.getWindowManager().getDefaultDisplay();
    boolean wide = activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
    switch (display.getRotation()) {
        case Surface.ROTATION_0:
            return wide ? land : port;
        case Surface.ROTATION_90:
            return wide ? land : revP;
        case Surface.ROTATION_180:
            return wide ? revL : revP;
        case Surface.ROTATION_270:
            return wide ? revL : port;
        default:
            throw new AssertionError();
    }
}

private static boolean isLandscape270() {

    return android.os.Build.MANUFACTURER.equals("Amazon")
        && !(android.os.Build.MODEL.equals("KFOT") || android.os.Build.MODEL.equals("Kindle Fire"));
}

isLandscape270() определяет, является ли устройство Kindle 2-го поколения или новее (см. эту ссылку , получая MODEL от этогоссылка ). Я не знаю, должны ли быть включены и другие устройства, пожалуйста, прокомментируйте, если вам что-то известно.

Кроме того, для API> = 18 просто используется setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED). Я только проверялчто на эмуляторах, пожалуйста, прокомментируйте, если у него есть проблемы на реальных устройствах.

2 голосов
/ 07 июля 2011

Использование: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR), поскольку ориентация определяется датчиком физической ориентации: дисплей будет вращаться в зависимости от того, как пользователь перемещает устройство.Это позволяет любое из 4 возможных вращений, независимо от того, что устройство обычно делает (например, некоторые устройства обычно не используют поворот на 180 градусов).И ваш код должен работать на Xoom тоже ...

1 голос
/ 06 июля 2011

В вашем AndroidManifest.xml вы можете объявить активность только пейзажной или портретной.Просто добавьте атрибут screenOrientation к элементу действия:

http://developer.android.com/guide/topics/manifest/activity-element.html

0 голосов
/ 22 сентября 2011

Мое решение:

int orientation=act.getResources().getConfiguration().orientation;
int rotation=act.getWindowManager().getDefaultDisplay().getOrientation();
if (orientation==Configuration.ORIENTATION_PORTRAIT)
   {if (rotation==Surface.ROTATION_0 || rotation==Surface.ROTATION_270) //0 for phone, 270 for tablet
       {act.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
       }
    else
        {act.setRequestedOrientation(9);//instead of SCREEN_ORIENTATION_REVERSE_PORTRAIT when <= android 2.2
        }
   }
else
    {if (rotation==Surface.ROTATION_90 || rotation==Surface.ROTATION_0) //90 for phone, 0 for tablet
        {act.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
     else
         {act.setRequestedOrientation(8);//instead of SCREEN_ORIENTATION_REVERSE_LANDSCAPE when <= android 2.2
         }
    }
...