Android: deshabilita temporalmente los cambios de orientación en una actividad
Mi actividad principal tiene algún código que hace algunos cambios en la base de datos que no deben interrumpirse. Estoy haciendo el trabajo pesado en otro hilo, y utilizando un diálogo de progreso que establecí como no cancelable. Sin embargo, me di cuenta de que si girar mi teléfono se reinicia la actividad que es muy malo para el proceso que se estaba ejecutando, y obtuve un cierre de la Fuerza.
Lo que quiero hacer es desactivar programaticamente los cambios de orientación de pantalla hasta que se complete mi proceso, momento en el que los cambios de orientación están habilitados.
- Android: orientación manual de la pantalla sin reiniciar la actividad?
- ¿La aplicación de Android restablece el cambio de orientación, la mejor manera de manejar?
- Orientación de Android AR
- DialogFragment Orientación Cambiar el bloqueo con getActivity ()
- Ayuda natural de la orientación del sensor de Android
- Cómo cambiar la orientación de bloqueo en Android?
- El método getOrientation () de Android devuelve resultados incorrectos
- Problema con la orientación personalizada de la imagen de Android
- Cómo obtener NUEVA anchura / altura del diseño raíz en onConfigurationChanged?
- Manera correcta de usar SOLO Giroscopio y Acelerómetro para obtener el ángulo de corriente fiable en cualquier eje de ANDROID
- Cambiar la orientación de la pantalla - Android 3.2 en VirtualBox
- Android YouTube api v3 - orientación
- ¿Cómo puedo especificar diferentes diseños para orientaciones de retrato y de paisaje?
Como explicó Chris en su auto-respuesta , llamando
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
y entonces
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
Realmente funciona como el encanto … en dispositivos reales!
No pienses que se ha roto al probar en el emulador, el atajo ctrl + F11 SIEMPRE cambia la orientación de la pantalla, sin emular los movimientos de los sensores.
EDIT: esta no fue la mejor respuesta posible. Como se explica en los comentarios, hay problemas con este método. La verdadera respuesta está aquí .
Ninguna de las otras respuestas hizo el truco perfectamente para mí, pero aquí es lo que encontré que hace.
Bloquear la orientación a la corriente …
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Al cambiar la orientación se debe permitir de nuevo, volver a la configuración predeterminada …
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
Aquí hay una solución más completa y actualizada que funciona para la API 8+, funciona para retratos inversos y paisaje y funciona en una pestaña Galaxy donde la orientación "natural" es de paisaje (llamada activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
para desbloquear la orientación):
@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); } }
Encontré la respuesta. Para ello, en una Actividad puede llamar a setRequestedOrientation(int)
con uno de los valores especificados aquí: http://developer.android.com/reference/android/R.attr.html#screenOrientation
Antes de patear mi hilo llamé a setRequestedOrientation(OFF)
(OFF = nosensor) y cuando el hilo se hizo llamé setRequestedOrientation(ON)
(ON = sensor). Funciona de maravilla.
Para manejar también los modos de orientación inversa, he utilizado ese código para fijar la orientación de la actividad:
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; }
Y para permitir de nuevo la orientación:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
Gracias a todos. He modificado la solución Pilot_51, para asegurarme de restaurar el estado anterior. También lancé un cambio para apoyar las pantallas que no son de paisaje y no de retrato (pero no las he probado en tal pantalla).
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); }
Luego para restaurarlo
setRequestedOrientation(prevOrientation);
Utilice setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
Para bloquear la orientación actual, ya sea horizontal o vertical.
Utilice setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
Para desbloquear la orientación.
Aquí hay una solución que funciona cada vez y conserva la orientación actual (utilizando Activity.Info.SCREEN_ORIENTATION_PORTRAIT
establece a 0 ° por ejemplo, pero el usuario puede tener una orientación de 180 ° como actual).
// 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 }
Esto funciona prefecto para mí. Resuelve el problema con diversa "orientación natural" de la tableta / del teléfono;)
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); }
Utilice ActivityInfo.SCREEN_ORIENTATION_USER
si desea girar la pantalla sólo si está activada en el dispositivo.
He llegado con una solución que depende de la rotación de la pantalla y luego decide la orientación del dispositivo. De conocer la orientación podemos bloquear la orientación y liberarla más tarde cuando sea necesario. Esta solución también puede determinar si el dispositivo en el modo de paisaje reverso .
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; } }
Luego, si necesitamos liberar la orientación, podemos llamar a este método:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
Creo que este código es más fácil de leer.
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); } } }
He encontrado que una combinación de valores de rotación / orientación existentes son necesarios para cubrir las cuatro posibilidades; Hay los valores de retrato / paisaje y la orientación natural del dispositivo. Digamos que la orientación natural de los dispositivos tendrá un valor de rotación de 0 grados cuando la pantalla está en su orientación "natural" vertical u horizontal. Del mismo modo, habrá un valor de rotación de 90 grados cuando está en el paisaje o el retrato (observe que es opuesto a la orientación @ 0 grados). Por lo tanto, los valores de rotación que no sean 0 o 90 grados implicarán orientación "Inversa". Ok, he aquí un código:
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 ); }
No me gustó la mayoría de las respuestas aquí, ya que en el desbloqueo que lo puso a UNSPECIFIED en contraposición al estado anterior. ProjectJourneyman lo tuvo en cuenta, lo cual fue genial, pero preferí el código de bloqueo de Roy. Por lo tanto, mi recomendación sería una mezcla de los dos:
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); } }
Puedes usar
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; } }
Usar esa línea de código
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
En su actividad en el método de creación
- Cómo utilizar isInEditMode () para ver el diseño con la vista personalizada en el editor
- Cual es la diferencia entre sendStickyBroadcast y sendBroadcast en Android