2010-08-31 2 views
97

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

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

+1

Посмотрите на Http: // StackOverflow.com/questions/6599770/screen-orientation-lock – diyism

+0

Поскольку никто не упоминает эту часть, вам захочется импортировать android.content.pm.ActivityInfo, чтобы использовать идентификатор ActivityInfo. – zsalwasser

+1

Refer: http://stackoverflow.com/a/32885911/2673792 для лучшего решения –

ответ

143

Как пояснялось Крисом в Его self-answer, называя

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); 

, а затем

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); 

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

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

EDIT: это был не самый лучший ответ. Как поясняется в комментариях, с этим методом возникают проблемы. The real answer is here.

+0

Я не мог найти эти константы. Спасибо за это. –

+36

Проблема с этими методами ... Похоже, если вы вызываете setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); когда устройство не использует ориентацию по умолчанию, тогда ориентация активности немедленно изменяется (уничтожается и воссоздается) до ориентации по умолчанию устройства. Например, на телефоне, если вы держите его в альбомной ориентации, тогда при переключении датчиков активность переключается на портретную и обратно в альбомную. Аналогичная проблема с Archos A5 IT: использование его в портрете приводит к переключению активности на пейзаж и обратно на портрет. –

+1

Настоящий ответ на исходный вопрос есть: http://stackoverflow.com/questions/3821423/background-task-progress-dialog-orientation-change-is-there-any-100-working/3821998#3821998 –

14

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

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

38

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

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

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

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

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 
+9

Проблема заключается в том, что 'Configuration.ORIENTATION_PORTRAIT' будет возвращен в обоих ландшафтных режимах (т. Е.« Нормальный »и наоборот). Поэтому, если телефон находится в обратном направлении ландшафта, и вы установите его на 'ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE', он перевернется вверх ногами. В API 9 ActivityInfo вводит константу SCREEN_ORIENTATION_REVERSE_LANDSCAPE', но я не вижу способа определить такую ​​ориентацию через класс «Конфигурация». –

+1

Это сработало. Ответ на вышеупомянутую проблему находится в этом ответе. http://stackoverflow.com/a/10453034/1223436 – Zack

+0

Работал как очарование для моих нужд, блестящее спасибо – user2029541

10

Спасибо всем. Я изменил решение 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); 
+0

Хороший материал - не знаю, почему вы не использовали «переключатель». – GJTorikian

+0

Забыл очистить и переключиться на переключатель после того, как я добавил третий вариант. – ProjectJourneyman

+0

Я нашел, что это работает без необходимости получать текущую конфигурацию, если у вас нет доступа к объекту активности, но только контекст ActivityInfo.SCREEN_ORIENTATION_NOSENSOR | ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED – max4ever

33

Вот более полный и на сегодняшний день решение, которое работает для API 8+, работает для обратного портрета и пейзажа, и работает на вкладке Галактики, где «естественное» ориентация пейзаж (назовем 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); 
    } 
} 
+0

Этот ответ отлично работал для меня. – Phillip

+0

Работал отлично для меня с планшетом и телефонами. – ScruffyFox

+0

Единственный правильный ответ, который работает на всех устройствах для меня. – amdev

0

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

-1

использовать эту строку кода

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

в урах активности OnCreate метод

15

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

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); 
+2

Это на самом деле правильный способ достижения этого –

1

Это работает префект для меня. Это решает проблему с другой «естественной ориентацией» таблетки/телефона;)

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

     Configuration config = getResources().getConfiguration(); 
     int naturalOrientation; 

     if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) && 
       config.orientation == Configuration.ORIENTATION_LANDSCAPE) 
       || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && 
       config.orientation == Configuration.ORIENTATION_PORTRAIT)) { 
      naturalOrientation = Configuration.ORIENTATION_LANDSCAPE; 
     } else { 
      naturalOrientation = Configuration.ORIENTATION_PORTRAIT; 
     } 

     // because getRotation() gives "rotation from natural orientation" of device (different on phone and tablet) 
     // we need to update rotation variable if natural orienation isn't 0 (mainly tablets) 
     if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE) 
      rotation = ++rotation % 4; 

     switch (rotation) { 
      case Surface.ROTATION_0: //0 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
       break; 
      case Surface.ROTATION_90: //1 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
       break; 
      case Surface.ROTATION_180: //2 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
       break; 
      case Surface.ROTATION_270: //3 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
       break; 
     } 
    } else { 
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 
    } 
0

Я пришел с решением, которое зависит от вращения дисплея, а затем решает ориентацию устройства. Из знания ориентации мы можем заблокировать ориентацию и освободить ее позже, когда это необходимо. Это решение также может определить, находится ли устройство в обратном пейзаже.

private void lockOrientation(){ 
    switch (((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation()) { 


     // Portrait 
     case Surface.ROTATION_0: 
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
      break; 


     //Landscape  
     case Surface.ROTATION_90: 
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
      break; 


     // Reversed landscape 
     case Surface.ROTATION_270: 
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);    
      break; 
    } 
} 

Тогда позже, если нам нужно, чтобы освободить ориентацию, мы можем назвать этот метод:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 
0

Я думаю, что этот код легче читать.

private void keepOrientation() { 

    int orientation = getResources().getConfiguration().orientation; 
    int rotation = getWindowManager().getDefaultDisplay().getRotation(); 

    switch (rotation) { 
     case Surface.ROTATION_0: 
      if (orientation == Configuration.ORIENTATION_PORTRAIT) { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
      } else { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
      } 
      break; 
     case Surface.ROTATION_90: 
      if (orientation == Configuration.ORIENTATION_PORTRAIT) { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
      } else { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
      } 
      break; 
     case Surface.ROTATION_180: 
      if (orientation == Configuration.ORIENTATION_PORTRAIT) { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
      } else { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
      } 
      break; 
     default: 
      if (orientation == Configuration.ORIENTATION_PORTRAIT) { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
      } else { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
      } 
    } 
} 
0

Я нашел, что сочетание существующих значений поворота/ориентации необходимо для покрытия четырех возможностей; есть портрет/пейзаж и естественная ориентация устройства. Предположим, что естественная ориентация устройств будет иметь значение поворота 0 градусов, когда экран находится в «естественной» портретной или альбомной ориентации. Точно так же будет значение поворота 90 градусов, когда оно находится в ландшафтном или портретном (обратите внимание, что оно противоположно ориентации на 0 градусов). Таким образом, значения вращения, которые не равны 0 или 90 градусов, будут означать «обратную» ориентацию. Хорошо, вот некоторый код:

public enum eScreenOrientation 
{ 
PORTRAIT (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT), 
LANDSCAPE (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE), 
PORTRAIT_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT), 
LANDSCAPE_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE), 
UNSPECIFIED_ORIENTATION (ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 

    public final int activityInfoValue; 

    eScreenOrientation (int orientation) 
    { 
     activityInfoValue = orientation; 
    } 
} 



public eScreenOrientation currentScreenOrientation () 
{ 
    final int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); 

    final int orientation = getResources().getConfiguration().orientation; 
    switch (orientation) 
    { 
    case Configuration.ORIENTATION_PORTRAIT: 
     if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) 
      return eScreenOrientation.PORTRAIT; 
     else 
      return eScreenOrientation.PORTRAIT_REVERSE; 
    case Configuration.ORIENTATION_LANDSCAPE: 
     if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) 
      return eScreenOrientation.LANDSCAPE; 
     else 
      return eScreenOrientation.LANDSCAPE_REVERSE; 
    default: 
     return eScreenOrientation.UNSPECIFIED_ORIENTATION; 
    } 
} 

public void lockScreenOrientation () 
    throws UnsupportedDisplayException 
{ 
    eScreenOrientation currentOrientation = currentScreenOrientation(); 
    if (currentOrientation == eScreenOrientation.UNSPECIFIED_ORIENTATION) 
     throw new UnsupportedDisplayException("Unable to lock screen - unspecified orientation"); 
    else 
     setRequestedOrientation(currentOrientation.activityInfoValue); 
} 

public void unlockScreenOrientation () 
{ 
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 
} 
4

Вот решение, которое работает каждый раз, и сохраняет текущую ориентацию (с использованием 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); 
} 
+2

Стоит упомянуть: API 18+ только –

+1

Это работает, красиво. – instanceof

0

Я не люблю большинство ответов здесь, так как в разблокировке они установили его UNSPECIFIED в отличие от предыдущего состояния. ProjectJourneyman принял это во внимание, что было здорово, но я предпочел код блокировки Роя. Итак, моя рекомендация будет смесь из двух:

private int prevOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 

private void unlockOrientation() { 
    setRequestedOrientation(prevOrientation); 
} 

@SuppressWarnings("deprecation") 
@SuppressLint("NewApi") 
private void lockOrientation() { 
    prevOrientation = getRequestedOrientation(); 
    Display display = 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) 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
      else 
       setRequestedOrientation(9/* reversePortait */); 
      break; 
     case Surface.ROTATION_180: 
      if (height > width) 
       setRequestedOrientation(9/* reversePortait */); 
      else 
       setRequestedOrientation(8/* reverseLandscape */); 
      break; 
     case Surface.ROTATION_270: 
      if (width > height) 
       setRequestedOrientation(8/* reverseLandscape */); 
      else 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
      break; 
     default : 
      if (height > width) 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
      else 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
    } 
} 
9

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

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

+0

Спасибо Matt для форматирования текста. –

+0

Лучшее решение для короткой временной блокировки. Не вмешиваться в текущую ориентацию датчика. –

+0

работает над Build.VERSION.SDK_INT> = 18, более полный ответ задается tdjprog на этой странице https://stackoverflow.com/a/41812971/5235263 – benbas1982

3
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 
} 
+0

Не могли бы вы добавить некоторые объяснения в свой ответ? – slfan

+0

, когда у вас есть задание в фоновом режиме, просто вызовите setLockScreenOrientation (true), чтобы заблокировать ориентацию и предотвратить уничтожение текущей активности, чтобы воссоздать ее. когда вы завершите выполнение этих заданий, вызовите setLockScreenOrientation (false). – tdjprog

+0

это лучший ответ! – Fakher

0

Вы можете использовать

public void swapOrientaionLockState(){ 
    try{ 
     if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1) { 
      Display defaultDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
      Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, defaultDisplay.getRotation()); 
      Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0); 
     } else { 
      Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 1); 
     } 

     Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, !orientationIsLocked() ? 1 : 0); 

    } catch (Settings.SettingNotFoundException e){ 
     e.printStackTrace(); 
    } 
} 

public boolean orientationIsLocked(){ 
    if(canModifiSetting(mContext)){ 
     try { 
      return Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0; 
     } catch (Settings.SettingNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 
    return false; 
} 

public static boolean canModifiSetting(Context context){ 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     return Settings.System.canWrite(context); 
    } else { 
     return true; 
    } 
} 
Смежные вопросы