Android: временно отключите изменения ориентации в Activity - PullRequest
112 голосов
/ 31 августа 2010

В моей основной деятельности есть некоторый код, который вносит некоторые изменения в базу данных, которые не должны прерываться. Я делаю тяжелую работу в другом потоке и использую диалог прогресса, который я установил как неотменяемый. Тем не менее, я заметил, что если я поворачиваю свой телефон, он перезапускает действие, которое ДЕЙСТВИТЕЛЬНО плохо для запущенного процесса, и я получаю Force Close.

То, что я хочу сделать, это программно отключить изменения ориентации экрана, пока мой процесс не завершится, и в это время изменения ориентации включены.

Ответы [ 17 ]

160 голосов
/ 01 сентября 2010

Как объяснил Крис в своем самоответе , позвонив

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

, а затем

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

действительно работает как шарм ... на реальных устройствах!

Не думайте, что он сломался при тестировании на эмуляторе, сочетание клавиш ctrl + F11 ВСЕГДА меняет ориентацию экрана, не эмулируя движения датчиков.

РЕДАКТИРОВАТЬ: это был не самый лучший ответ. Как объяснено в комментариях, есть проблемы с этим методом. Реальный ответ здесь .

41 голосов
/ 06 ноября 2010

Ни один из других ответов не помог мне, но вот что я нашел.

Блокировка ориентации на текущую ...

if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

При изменении ориентации должно бытьразрешено снова, установить обратно по умолчанию ...

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
35 голосов
/ 17 мая 2013

Вот более полное и современное решение, которое работает для API 8+, работает для реверсивного портрета и пейзажа и работает на вкладке Galaxy, где «естественной» ориентацией является альбомная (вызовите activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) для разблокировки ориентации):

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
public static void lockActivityOrientation(Activity activity) {
    Display display = activity.getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int height;
    int width;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
        height = display.getHeight();
        width = display.getWidth();
    } else {
        Point size = new Point();
        display.getSize(size);
        height = size.y;
        width = size.x;
    }
    switch (rotation) {
    case Surface.ROTATION_90:
        if (width > height)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        break;
    case Surface.ROTATION_180:
        if (height > width)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        break;          
    case Surface.ROTATION_270:
        if (width > height)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        break;
    default :
        if (height > width)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}
17 голосов
/ 16 ноября 2013

Для управления режимами обратной ориентации я использовал этот код для фиксации ориентации деятельности:

int rotation = getWindowManager().getDefaultDisplay().getRotation();

    switch(rotation) {
    case Surface.ROTATION_180:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        break;
    case Surface.ROTATION_270:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);         
        break;
    case  Surface.ROTATION_0:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        break;
    case Surface.ROTATION_90:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        break;
    }

И снова разрешить ориентацию:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
16 голосов
/ 01 октября 2015

Используйте setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); для блокировки текущей ориентации, будь то альбомная или книжная ориентация.

Используйте setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); для разблокировки ориентации.

14 голосов
/ 31 августа 2010

Я нашел ответ. Для этого в Activity вы можете вызвать setRequestedOrientation(int) с одним из значений, указанных здесь: http://developer.android.com/reference/android/R.attr.html#screenOrientation

Прежде, чем я начал свою нить, я позвонил setRequestedOrientation(OFF) (OFF = nosensor), и когда нить была закончена, я позвонил setRequestedOrientation(ON) (ON = датчик). Работает как шарм.

10 голосов
/ 01 апреля 2011

Спасибо всем.Я изменил решение Pilot_51, чтобы убедиться, что я восстановил предыдущее состояние.Я также добавил изменения для поддержки не альбомных и не портретных экранов (но не тестировал их на таком экране).

prevOrientation = getRequestedOrientation();
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}

Затем, чтобы восстановить его

setRequestedOrientation(prevOrientation);
6 голосов
/ 23 января 2017
protected void setLockScreenOrientation(boolean lock) {
    if (Build.VERSION.SDK_INT >= 18) {
        setRequestedOrientation(lock?ActivityInfo.SCREEN_ORIENTATION_LOCKED:ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        return;
    }

    if (lock) {
        switch (getWindowManager().getDefaultDisplay().getRotation()) {
            case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; // value 1
            case 2: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; // value 9
            case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // value 0
            case 3: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; // value 8
        }
    } else
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // value 10
}
5 голосов
/ 28 января 2015

Вот решение, которое работает каждый раз и сохраняет текущую ориентацию (например, Activity.Info.SCREEN_ORIENTATION_PORTRAIT устанавливает 0 °, но пользователь может иметь ориентацию 180 ° в качестве текущей).

// Scope: Activity

private void _lockOrientation() {
    if (super.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
    } else {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
    }
}

private void _unlockOrientation() {
    super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
1 голос
/ 19 сентября 2013

используйте ActivityInfo.SCREEN_ORIENTATION_USER, если хотите повернуть экран, только если он включен на устройстве.

...