Как заблокировать ориентацию во время выполнения

107

Есть ли способ заблокировать ориентацию во время выполнения? Например, я хотел бы разрешить пользователю заблокировать экран в альбомной ориентации, если пользователь в настоящее время находится в альбомной ориентации, и переключить опцию меню.

Джаред
источник

Ответы:

133
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Вызывается для действия, оно будет зафиксировано в альбомной ориентации. Ищите другие флаги в классе ActivityInfo. Вы можете заблокировать его обратно в портретное положение или сделать его управляемым сенсором / слайдером.

Подробнее здесь: http://www.devx.com/wireless/Article/40792

Хасеман
источник
13
Хорошо, спасибо. Это прекрасно работает. Это получит текущую ориентацию. getResources (). getConfiguration (). Ориентация
Джаред
7
Осторожный! Вам нужно различать то, что возвращает getConfiguration (), и то, что хочет setRequestedOrientation - подробности см. В моем ответе ниже
Энди Вайнштейн,
есть проблема с этим подходом. Обязательно прочтите комментарий к этому ответу
Bugs Happen
но он устанавливает одинаковую ориентацию для всей деятельности, есть ли другой способ изменить ориентацию
silverFoxA
106

Будьте осторожны с разницей между тем, что возвращает getConfiguration, и тем, что хочет setRequestedOrientation - они оба имеют тип int, но исходят из разных определений констант.

Вот как заблокировать текущую ориентацию, разрешив при этом поворот на 180 градусов

int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
else {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
Энди Вайнштейн
источник
13
Вы можете предпочесть использовать SCREEN_ORIENTATION_USER_LANDSCAPE, так как это не позволяет поворачивать на 180 градусов, если пользователь отключил поворот экрана в настройках. Точно так же при переключении обратно на свободное вращение SCREEN_ORIENTATION_USER лучше, чем SCREEN_ORIENTATION_SENSOR, поскольку последний допускает свободное вращение, даже если настройки запрещают.
Стив Уоринг
Гениально! Надо добавить, что при переключении на обратную ориентацию перенастройки не происходит. По крайней мере, на устройствах, на которых я это тестировал. Это действительно важно знать, если вы хотите остановить реконфигурацию во время некоторых диалоговых шоу и т. Д.
sberezin
47

Это работает на устройствах с обратным портретом и обратным ландшафтом.

Ориентация блокировки:

    int orientation = getActivity().getRequestedOrientation();
    int rotation = ((WindowManager) getActivity().getSystemService(
            Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
    switch (rotation) {
    case Surface.ROTATION_0:
        orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        break;
    case Surface.ROTATION_90:
        orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        break;
    case Surface.ROTATION_180:
        orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
        break;
    default:
        orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
        break;
    }

    getActivity().setRequestedOrientation(orientation);

Разблокировать ориентацию:

   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
пстоппани
источник
5
Получить "Returns the rotation of the screen from its "natural" orientation." источник вращения . Таким образом, на телефоне сообщение «ROTATION_0 - портретный», вероятно, правильно, но на планшете его «естественная» ориентация, скорее всего, будет альбомной, и ROTATION_0 должен вернуть альбомный, а не портретный.
jp36
@ jp36, я тестировал Nexus 7, у которого естественная ориентация такая же, как у телефона. Спасибо за тестирование на планшете большего размера (которого у меня нет).
pstoppani
1
Как сказал jp36, он не работает на планшетах с естественной ландшафтной ориентацией!
DominicM
Как мы проверяем обратный портрет в устройстве ??
AndyBoy
27

Похоже, у меня был похожий случай. Я хотел поддержать любую ориентацию, но мне нужно было оставаться в текущей ориентации после определенного момента в рабочем процессе. Мое решение было:

При входе в защищенный рабочий процесс:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

При выходе из защищенного рабочего процесса:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
Стефан Бахерт
источник
2
Это не касается OQ, по крайней мере, на Android> = 16. setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) может установить устройство в альбомную ориентацию, даже если оно было в портретной ориентации, тогда как вопрос относится к заданной ориентации блокировки.
greg7gkb
3
для меня установка его на носенсор возвращает меня в портретный режим, если я был в альбомной ориентации, я использовал вместо этого SCREEN_ORIENTATION_LOCKED, и это сработало для меня
Джиммар
1
@JiMMaR SCREEN_ORIENTATION_LOCKED - лучший способ для Android> = 18. Но если вы нацеливаетесь на что-то меньшее, это не сработает. Я предлагаю использовать ответ jp36 ниже.
Патрик Боос
23

Альтернатива ответу @pstoppani с поддержкой планшетов (как и ответ @pstoppani, это будет работать только на устройствах> 2.2) -
Протестировано на Samsung Galaxy SIIIиSamsung Galaxy Tab 10.1

public static void lockOrientation(Activity activity) {
    Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int rotation = display.getRotation();
    int tempOrientation = activity.getResources().getConfiguration().orientation;
    int orientation = 0;
    switch(tempOrientation)
    {
    case Configuration.ORIENTATION_LANDSCAPE:
        if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
            orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        else
            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
        break;
    case Configuration.ORIENTATION_PORTRAIT:
        if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270)
            orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        else
            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
    }
    activity.setRequestedOrientation(orientation);
}
jp36
источник
Спасибо, это работает отлично , но я не понимаю , что почему это проверка с ||в rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90и с rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270. Итак, у меня есть 2 сомнения :::: во-первых, почему, ROTATION_0а не ROTATION_180во втором случае, а во-вторых, почему проверять 0 градусов с 90, а не 180 ??
AndyBoy
@AndyBoy это связано с ориентацией устройств по умолчанию. Обычно телефоны по умолчанию имеют портретную ориентацию, что означает, что вращение возвращает ноль для портрета, но на некоторых планшетах по умолчанию используется альбомная ориентация, что означает, что вращение возвращает ноль для альбомной ориентации. Таким образом, различные ||проверки обрабатывают две возможные ориентации по умолчанию на основе ландшафтной и портретной ориентации устройства.
jp36
5

Вот мой код, вы можете заблокировать одним из этих методов свой экран и после завершения задачи разблокировать его с помощью unlockOrientation:

/** Static methods related to device orientation. */
public class OrientationUtils {
    private OrientationUtils() {}

    /** Locks the device window in landscape mode. */
    public static void lockOrientationLandscape(Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    /** Locks the device window in portrait mode. */
    public static void lockOrientationPortrait(Activity activity) {
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    /** Locks the device window in actual screen mode. */
    public static void lockOrientation(Activity activity) {
        final int orientation = activity.getResources().getConfiguration().orientation;
        final int rotation = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();

        // 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;

        // Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO
        if (!BuildVersionUtils.hasGingerbread()) {
            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);
            }
        }
    }

    /** Unlocks the device window in user defined screen mode. */
    public static void unlockOrientation(Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
    }

}
Madx
источник
0

Вот преобразование Xamarin ответа @pstoppani выше.

ПРИМЕЧАНИЕ: это для фрагмента, замените Activity. с этим. если используется в деятельности.

public void LockRotation()
{
    ScreenOrientation orientation;

    var surfaceOrientation = Activity.WindowManager.DefaultDisplay.Rotation;

    switch (surfaceOrientation) {
        case SurfaceOrientation.Rotation0:
            orientation = ScreenOrientation.Portrait;
            break;
        case SurfaceOrientation.Rotation90:
            orientation = ScreenOrientation.Landscape;
            break;
        case SurfaceOrientation.Rotation180:
            orientation = ScreenOrientation.ReversePortrait;
            break;
        default:
            orientation = ScreenOrientation.ReverseLandscape;
            break;
    }

    Activity.RequestedOrientation = orientation;
}

public void UnlockRotation()
{
    Activity.RequestedOrientation = ScreenOrientation.Unspecified;
}

Это не проверено, поскольку до его использования использовался другой подход, но может быть полезен.

WickedW
источник
Это тот же ответ, что и у pstoppani, и он не работает на планшете.
Тим Атин