Cómo bloquear la orientación durante el tiempo de ejecución

107

¿Hay alguna forma de bloquear la orientación durante el tiempo de ejecución? Por ejemplo, me gustaría permitirle al usuario bloquear la pantalla en horizontal si el usuario está actualmente en horizontal y alternar la opción del menú.

Jared
fuente

Respuestas:

133
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Llamado a una actividad, lo bloqueará en el paisaje. Busque las otras banderas en la clase ActivityInfo. Puede volver a bloquearlo en retrato o hacer que sea controlado por sensor / control deslizante.

Más información aquí: http://www.devx.com/wireless/Article/40792

haseman
fuente
13
OK gracias. Esto funciona muy bien. Eso obtendrá la orientación actual. getResources (). getConfiguration (). Orientación
Jared
7
¡Cuidado! Debe diferenciar entre lo que devuelve getConfiguration () y lo que desea setRequestedOrientation; consulte mi respuesta a continuación para obtener más detalles
Andy Weinstein
hay un problema con este enfoque. Asegúrese de leer el comentario de esta respuesta
errores ocurren
pero establece la misma orientación para toda la actividad, ¿hay alguna otra forma en la que podamos cambiar la orientación
silverFoxA
106

Tenga cuidado con la diferencia entre lo que devuelve getConfiguration y lo que desea setRequestedOrientation: ambos son int, pero provienen de diferentes definiciones constantes.

A continuación, se explica cómo bloquear la orientación actual y permitir giros de 180 grados

int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
else {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
Andy Weinstein
fuente
13
Es posible que prefiera utilizar SCREEN_ORIENTATION_USER_LANDSCAPE ya que esto no permite los giros de 180 grados si el usuario ha desactivado la rotación de pantalla en la configuración. De manera similar, al volver a la rotación libre, SCREEN_ORIENTATION_USER es mejor que SCREEN_ORIENTATION_SENSOR ya que este último permite la rotación libre incluso si la configuración dice que no.
Steve Waring
¡Brillante! Es necesario agregar que cuando cambia a la orientación inversa, la reconfiguración no ocurre. Al menos en dispositivos en los que lo he probado. Es muy importante saber si desea detener la reconfiguración durante algunos programas de diálogo, etc.
sberezin
47

Esto funciona en dispositivos con retrato inverso y paisaje inverso.

Orientación de bloqueo:

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

Desbloquear orientación:

   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
pstoppani
fuente
5
Obtenga la "Returns the rotation of the screen from its "natural" orientation." fuente de rotación . Por lo tanto, en un teléfono que dice que ROTATION_0 es vertical, es probable que sea correcto, pero en una tableta, su orientación "natural" es probablemente horizontal y ROTATION_0 debería devolver horizontal en lugar de vertical.
jp36
@ jp36, probé en un Nexus 7 que tiene una orientación natural que es la misma que la de un teléfono. Gracias por probar en una tableta más grande (que no tengo).
pstoppani
1
Como dijo jp36, ¡no funciona en tabletas con una orientación de paisaje natural!
DominicM
¿Cómo probamos el retrato inverso en el dispositivo?
AndyBoy
27

Parecía haber tenido un caso similar. Quería apoyar cualquier orientación, pero necesitaba permanecer en la orientación actual después de cierto punto en el flujo de trabajo. Mi solucion fue:

Al entrar en el flujo de trabajo protegido:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

Al salir del flujo de trabajo protegido:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
stefan bachert
fuente
2
Esto no aborda el OQ, al menos en Android> = 16. setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) podría configurar el dispositivo en horizontal incluso si estaba en vertical, mientras que la pregunta se refiere a la orientación de bloqueo que se proporcionó.
greg7gkb
3
para mí, configurarlo en sensor de nariz me lleva de vuelta al modo retrato si estaba en paisaje, usé SCREEN_ORIENTATION_LOCKED en su lugar y funcionó para mí
Jimmar
1
@JiMMaR SCREEN_ORIENTATION_LOCKED es la mejor manera para Android> = 18. Pero en caso de que apuntes a algo más bajo, eso no funciona. Sugiero usar la respuesta de jp36 a continuación.
Patrick Boos
23

Alternativa a la respuesta @pstoppani con soporte para tabletas (al igual que con la respuesta @pstoppani, esto solo funcionará en dispositivos> 2.2)
-Probado en Samsung Galaxy SIIIySamsung 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
fuente
Gracias, está bien trabajando, pero no me entender que eso que es con cheque ||en rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90y con rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270. Entonces tengo 2 dudas :::: primero, ¿Por qué en ROTATION_0lugar de ROTATION_180en el segundo caso y otro por qué marcar 0 grados con 90 no 180?
AndyBoy
@AndyBoy tiene que ver con la orientación predeterminada de los dispositivos. Por lo general, los teléfonos tienen una orientación vertical predeterminada, lo que significa que la rotación devuelve cero para el retrato, pero algunas tabletas tienen un paisaje predeterminado, lo que significa que la rotación devuelve cero para el paisaje. Por lo tanto, las diferentes ||comprobaciones manejan las dos posibles orientaciones predeterminadas basadas en el dispositivo que informa horizontal o vertical.
jp36
5

Aquí está mi código, puede bloquear con uno de estos métodos su pantalla y una vez finalizada la tarea desbloquearla con 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
fuente
0

Aquí está la conversión de Xamarin de la respuesta de @pstoppani anterior.

NOTA: esto es para un Fragmento, reemplace Actividad. con esto. si se usa dentro de una actividad.

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

Esto no se ha probado con un enfoque diferente antes de usarlo, pero puede ser útil.

WickedW
fuente
Esta es la misma respuesta que la de pstoppani, y fallará en una tableta.
Tim Autin