Android: временно отключить изменения ориентации в деятельности
моя основная деятельность имеет некоторый код, который вносит некоторые изменения в базу данных, которые не должны быть прерваны. Я делаю тяжелую работу в другом потоке и использую диалог прогресса, который я установил как не отменяемый. Тем не менее, я заметил, что если я поверну свой телефон, он перезапустит активность, которая действительно плохо сказывается на запущенном процессе, и я получаю силу близко.
Что я хочу сделать, это программно отключить изменения ориентации экрана, пока мой процесс не завершится, в это время изменения ориентации включены.
17 ответов:
Как объяснил Крис в своем собственн-ответ, называя
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);а то
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);действительно работает как шарм... на реальных устройствах !
Не думайте, что он сломан при тестировании на эмуляторе, ярлык ctrl+F11 всегда меняет ориентацию экрана, не эмулируя движения датчиков.
EDIT: это был не самый лучший ответ. Как поясняется в комментариях, есть проблемы с этим методом. реальные ответ здесь.
ни один из других ответов не сделал трюк идеально для меня, но вот что я нашел, что делает.
блокировка ориентации на текущие...
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);когда изменение ориентации должно быть разрешено снова, установите значение по умолчанию...
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
вот более полное и актуальное решение, которое работает для 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); } }
чтобы управлять также режимами обратной ориентации, я использовал этот код для исправления ориентации активности:
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);
Я нашел ответ. Для этого в упражнении можно вызвать
setRequestedOrientation(int)с одним из значений, указанных здесь: http://developer.android.com/reference/android/R.attr.html#screenOrientationпрежде чем я начал свою нить, я позвонил
setRequestedOrientation(OFF)(OFF = nosensor) и когда поток был сделан, я позвонилsetRequestedOrientation(ON)(ВКЛ = датчик). Работает как шарм.
использовать
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);для блокировка текущей ориентации, будь то пейзаж или портрет.использовать
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);для разблокировки ориентации.
спасибо всем. Я изменил решение 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);
вот решение, которое работает каждый раз и сохраняет текущую ориентацию (используя
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); }
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 }
это работает идеально подходит для меня. Он решает проблему с различной "естественной ориентацией" планшета / телефона;)
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); }
использовать
ActivityInfo.SCREEN_ORIENTATION_USERЕсли вы хотите повернуть экран, только если он включен на устройстве.
Я придумал решение, которое зависит от поворота дисплея, а затем решает ориентацию устройства. Зная ориентацию, мы можем заблокировать ориентацию и освободить ее позже, когда это необходимо. Это решение также может определить, если устройство в обратный пейзаж режим.
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);
Я думаю, что этот код легче читать.
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 градусов, когда экран находится в его "естественной" портретной или альбомной ориентации. Точно так же будет значение поворота на 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 ); }
мне не понравилось большинство ответов здесь, так как в разблокировке они установили его в неуказанное, в отличие от предыдущего состояния. 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); } }
можно использовать
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; } }
использовать эту строку кода
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);в ur activity oncreate метод
Comments