¿Cómo detectar el cambio de orientación en el diseño en Android?

110

Acabo de implementar una función de cambio de orientación, por ejemplo, cuando el diseño cambia de vertical a horizontal (o viceversa). ¿Cómo puedo detectar cuándo terminó el evento de cambio de orientación?

El OrientationEventListenerno funcionó. ¿Cómo puedo recibir notificaciones sobre eventos de cambio de orientación de diseño?

user403015
fuente
En mi caso, se llamó a onCreate () cuando cambia la orientación.
Josiel Novaes

Respuestas:

293

Utilice el método de actividad onConfigurationChanged . Vea el siguiente código:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

También tienes que editar el apropiado en su archivo de manifiesto para incluir android: configChanges Solo vea el código a continuación:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

NOTA: con Android 3.2 (API nivel 13) o superior, el "tamaño de la pantalla" también cambia cuando el dispositivo cambia entre la orientación vertical y horizontal. Por lo tanto, si desea evitar que el tiempo de ejecución se reinicie debido a un cambio de orientación al desarrollar para el nivel de API 13 o superior, debe declarar android: configChanges = "orientación | screenSize" para el nivel de API 13 o superior .

Espero que esto te ayudará... :)

Dinesh Sharma
fuente
3
Esto es bueno, pero no carga el xml de diseño en la carpeta layout-land, usa los archivos de diseño xml vertical.
Programador
22
Codificador azteca, cuando incluye "android: configChanges =" orientación ", declara que manejará el cambio de orientación, lo que significa que su actividad no se volverá a crear cuando cambie a horizontal. En su lugar, se llama a onConfigurationChanged. Si no lo desea , podría usar una variable para recordar la orientación de su actividad y cada vez que vaya a Pausa (por ejemplo) para verificar si la orientación sigue siendo la misma.
Elena
14
Si está desarrollando para API nivel 13 (3.2) o superior, debe especificar android: configChanges = "Orientación | ScreenSize"; de lo contrario, onConfigurationChanged no se llamará: developer.android.com/guide/topics/resources/…
Arne
1
Hola, estoy creando mi aplicación con API 10 (Android 2.3.3). Y reconoce la orientación perfectamente cuando uso android: configChanges = "Orientation | keyboardHidden". Pero mi Nexus S que ejecuta Android 4.1.2 no detecta el cambio de orientación, ¿qué debo hacer?
Karthik Andhamil
2
use android: configChanges = "Orientación | ScreenSize" en lugar de android: configChanges = "Orientación | KeyboardHidden" en su archivo de manifiesto y verifique ... !!!
Dinesh Sharma
15

Para cargar el diseño de la disposición en tierra medios de carpeta que tiene dos diseños separados entonces usted tiene que hacer setContentViewen el onConfigurationChangedmétodo.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

Si solo tiene un diseño, entonces no es necesario crear setContentView en este método. simplemente

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Veerababu Medisetti
fuente
19
En lugar de anular, simplemente use layout / main.xml y layout-land / main.xml.
Jared Burrows
@JaredBurrows: consulte stackoverflow.com/questions/23789605/…
B. Clay Shannon
Quería detectar que mi actividad se terminó debido a una rotación de pantalla. Implementé el onConfigurationChanged(Configuration newConfig)método (como en esta respuesta), pero en lugar de manejarlo yo mismo, configuré una bandera booleana y luego llamé al recreate()método para que Android recreara la actividad en su forma normal.
aturdido
Un problema con el recreate()método es que hace que la pantalla parpadee en negro brevemente. Por esta razón, utilicé otro enfoque: (1) guardar el ancho de la pantalla en el onCreate(...), (2) comparar el ancho de la pantalla guardado con el ancho de la pantalla actual en cualquier método de ciclo de vida cuando se termina la actividad (por ejemplo onSaveInstanceState(...)).
aturdido
13

Solo quería mostrarte una forma de guardar todo tu Bundle después de onConfigurationChanged:

Crea un nuevo paquete justo después de tu clase:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

A continuación, después de "protected void onCreate", agregue esto:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

Si agrega esto, todas sus clases creadas en MainActivity se guardarán.

Pero la mejor manera es agregar esto en su AndroidManifest:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Nikolay Hristov
fuente
7
Esto es engañoso. La implementación onConfigurationChanged()hace que su instanceState no se destruya cuando cambia la orientación, por lo que no tiene que guardarlo. Es posible que desee guardarlo para otros eventos en el ciclo de vida de la actividad, pero no lo sé.
izzy
5

usa este método

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

Y no olvide agregar esto en su Androidmainfest.xml

android:configChanges="orientation|screenSize"

Me gusta esto

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>
Sai Gopi Me
fuente
2

Anular el método de la actividad onConfigurationChanged

Flavio
fuente
Me gustaría señalar que sin la siguiente línea dentro de la etiqueta <activity> en el manifiesto, la devolución de llamada onConfigurationChanged () ni siquiera se activaría. android: configChanges = "Orientación"
Sreekanth Karumanaghat
1

Solo quiero proponer otra alternativa que interesará a algunos de ustedes, de hecho, como se explicó anteriormente:

android:configChanges="orientation|keyboardHidden" 

implica que declaramos explícitamente el diseño que se inyectará.

Por si queremos mantener la inyección automática gracias a las carpetas layout-land y layout. Todo lo que tienes que hacer es agregarlo a onCreate:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

Aquí mostramos o no la barra de acciones según la orientación del teléfono

Z3nk
fuente
0

Cree una instancia de OrientationEventListenerclase y habilítela.

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();
James Fenn
fuente
2
Por favor, no destroces tu respuesta. Si desea eliminarlo, puede encontrar el botón Eliminar en la parte inferior izquierda de su respuesta.
CalvT
0

Si la respuesta aceptada no funciona para usted, asegúrese de no haber definido en el archivo de manifiesto:

android:screenOrientation="portrait"

Cual es mi caso.

Jiyeh
fuente
0

En caso de que esto sea útil para algunos desarrolladores más nuevos porque no está especificado anteriormente. Solo para ser muy explícito:

Necesita dos cosas si usa onConfigurationChanged :

  1. Un onConfigurationChangedmétodo en tu clase de actividad

  2. Especifique en su manifiesto qué cambios de configuración serán manejados por su onConfigurationChangedmétodo

El fragmento de manifiesto en las respuestas anteriores, aunque sin duda es correcto para la aplicación en particular a la que pertenece el manifiesto, NO es exactamente lo que necesita agregar en su manifiesto para activar el método onConfigurationChanged en su Clase de actividad. es decir, la entrada de manifiesto a continuación puede no ser correcta para su aplicación.

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

En la entrada de manifiesto anterior, hay varias acciones de Android para las android:configChanges=""que pueden activar onCreate en el ciclo de vida de su actividad.

Esto es muy importante: los que NO están especificados en el manifiesto son los que activan su onCreate y los especificados en el manifiesto son los que activan su onConfigurationChangedmétodo en su Clase de actividad.

Por lo tanto, debe identificar qué cambios de configuración debe manejar usted mismo. Para los con desafíos enciclopédicos de Android como yo, utilicé la ventana emergente de sugerencias rápidas en Android Studio y agregué casi todas las opciones de configuración posibles. Enumerar todos estos básicamente decía que yo manejaría todo y nunca se llamará a onCreate debido a las configuraciones.

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

Ahora, obviamente, no quiero manejar todo, así que comencé a eliminar las opciones anteriores una a la vez. Reconstruir y probar mi aplicación después de cada eliminación.

Otro punto importante : si solo hay una opción de configuración que se maneja automáticamente y que activa su onCreate (no la tiene enumerada en su manifiesto anterior), entonces parecerá que onConfigurationChangedno está funcionando. Debes poner todos los relevantes en tu manifiesto.

Terminé con 3 que estaban activando onCreate originalmente, luego probé en un S10 + y todavía estaba recibiendo el onCreate, así que tuve que hacer mi ejercicio de eliminación nuevamente y también necesitaba el |screenSize. Así que prueba en una selección de plataformas.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

Entonces mi sugerencia, aunque estoy seguro de que alguien puede hacer agujeros en esto:

  1. Agregue su onConfigurationChangedmétodo en su clase de actividad con un TOAST o LOG para que pueda ver cuándo está funcionando.

  2. Agregue todas las opciones de configuración posibles a su manifiesto.

  3. Confirma que tu onConfigurationChangedmétodo funciona probando tu aplicación.

  4. Elimina cada opción de configuración de tu archivo de manifiesto una a la vez, probando tu aplicación después de cada una.

  5. Pruebe en la mayor variedad de dispositivos posible.

  6. No copie / pegue mi fragmento anterior en su archivo de manifiesto. Las actualizaciones de Android cambian la lista, así que use las sugerencias emergentes de Android Studio para asegurarse de obtenerlas todas.

Espero que esto le ahorre a alguien algo de tiempo.

Mi onConfigurationChangedmétodo solo para obtener información a continuación. onConfigurationChangedse llama en el ciclo de vida después de que la nueva orientación esté disponible, pero antes de que se haya vuelto a crear la interfaz de usuario. Por lo tanto, el primero ifen verificar que la orientación funciona correctamente, y luego el segundo anidado ifpara ver la visibilidad de mi UI ImageView también funciona correctamente.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }
DMur
fuente
0

para la implementación de Kotilin en la forma más simple: solo se activa cuando la pantalla cambia de retrato <--> paisaje si necesita un dispositivo de detección de volteo (180 grados), deberá tabular los valores del sensor de gravedad

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


    }
}
alpha911
fuente