Actividad reiniciar en rotación Android

1380

En mi aplicación de Android, cuando giro el dispositivo (deslizo el teclado), Activityse reinicia mi ( onCreatese llama). Ahora, probablemente así es como se supone que debe ser, pero realizo muchas configuraciones iniciales en el onCreatemétodo, por lo que necesito:

  1. Ponga toda la configuración inicial en otra función para que no todo se pierda en la rotación del dispositivo o
  2. Haga que onCreateno se vuelva a llamar y el diseño simplemente se ajuste o
  3. Limite la aplicación a solo retrato para que onCreateno se llame.
Isaac Waller
fuente
44
¡También hay una explicación bastante completa sobre cómo retener tareas asincrónicas de larga duración durante los cambios de configuración de actividad en esta publicación de blog !
Adrian Monk
3
Esta no es una respuesta directa, ya que otros ya han respondido, pero lo invito a echar un vistazo a LogLifeCycle para comprender lo que sucede en sus aplicaciones de Android con respecto a los ciclos de vida.
Snicolas

Respuestas:

965

Usando la clase de aplicación

Dependiendo de lo que esté haciendo en su inicialización, podría considerar crear una nueva clase que se extienda Applicationy mover su código de inicialización a un onCreatemétodo anulado dentro de esa clase.

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

La onCreateclase en la aplicación solo se llama cuando se crea la aplicación completa, por lo que la actividad se reinicia en la orientación o los cambios de visibilidad del teclado no lo activarán.

Es una buena práctica exponer la instancia de esta clase como un singleton y exponer las variables de aplicación que está inicializando usando getters y setters.

NOTA: Deberá especificar el nombre de su nueva clase de Aplicación en el manifiesto para que se registre y se use:

<application
    android:name="com.you.yourapp.MyApplicationClass"

Reacción a los cambios de configuración [ACTUALIZACIÓN: esto está en desuso desde API 13; ver la alternativa recomendada ]

Como alternativa adicional, puede hacer que su aplicación escuche eventos que causarían un reinicio, como cambios de orientación y visibilidad del teclado, y manejarlos dentro de su Actividad.

Comience agregando el android:configChangesnodo al nodo manifiesto de su Actividad

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

o para Android 3.2 (API nivel 13) y más reciente :

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

Luego, dentro de la Actividad, anule el onConfigurationChangedmétodo y llame setContentViewpara forzar que el diseño de la GUI se vuelva a hacer en la nueva orientación.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}
Reto Meier
fuente
17
No creo que el segundo enfoque funcione. Lo intenté; una actividad con un EditText. Escribí un texto allí, cambié de orientación y el texto desapareció / reinicié.
Ted
231
Esperamos ver un método onRotate () en el futuro. Tener que preocuparse por cosas como esta es, francamente, frustrante.
Kelly Sutton
84
Tenga en cuenta que la Guía de desarrollo de Android advierte contra el uso de esto: Nota: El uso de ( android:configChanges) debe evitarse y usarse solo como último recurso. Lea Manejo de cambios en tiempo de ejecución para obtener más información sobre cómo manejar correctamente un reinicio debido a un cambio de configuración. En lugar de eso, para persistir los datos en los eventos de rotación, parecen preferir usar el onSaveInstanceState Bundle; o como @ Jon-O menciona , onRetainNonConfigurationInstance.
Jeffro
19
Esa es una mala solución, ya que solo reacciona a los cambios de configuración conocidos actualmente . Con las versiones más recientes de Android, pueden ocurrir otros cambios de configuración que este código no detectará (porque debe enumerar todos los cambios de configuración en el manifiesto). La solución de salvar el estado onRetainNonConfigurationChangeses más tolerante a fallas y directa.
Bananeweizen
16
Creo que debería agregar esta actualización en 3.2 a su respuesta, es bastante importante (solo enfrenté ese problema) y podría pasarse por alto.
Bigstones
185

Actualización para Android 3.2 y superior:

Precaución : a partir de Android 3.2 (API nivel 13), el "tamaño de la pantalla" también cambia cuando el dispositivo cambia entre orientación vertical y horizontal. Por lo tanto, si desea evitar reinicios en tiempo de ejecución debido al cambio de orientación al desarrollar para el nivel 13 de API o superior (según lo declarado por los atributos minSdkVersion y targetSdkVersion), debe incluir el "screenSize"valor además del "orientation"valor. Es decir, debes declarar android:configChanges="orientation|screenSize". Sin embargo, si su aplicación apunta al nivel de API 12 o inferior, entonces su actividad siempre maneja este cambio de configuración en sí mismo (este cambio de configuración no reinicia su actividad, incluso cuando se ejecuta en un dispositivo Android 3.2 o superior).

Gorm
fuente
1
Gracias por esa aclaración, ya que un comentario anterior sobre esto casi me envió a investigarlo. Actualmente estoy apuntando a API 8 y mi código no tiene screenSize en configChanges y puedo confirmar que funciona bien (sin reorientar) en el dispositivo que tengo que está ejecutando ICS.
Carl
Gracias por señalar esto, solo tenía android: configChanges = "oriente | screenSize" establecido, y el cambio de orientación estaba recreando mi Actividad, y por mi vida no pude entender por qué.
Christopher Perry
55
Agregar android: configChanges solo debe usarse como último recurso . Considere usar Fragmentsy en su setRetainInstancelugar.
Simon Forsberg el
El punto clave es screenSizepara Android 3.2 y superior, eso resolvió mi problema, ¡Gracias!
fantouch
127

En lugar de tratar de evitar que onCreate()se dispare por completo, tal vez intente verificar si Bundle savedInstanceStatese pasa al evento para ver si es nulo o no.

Por ejemplo, si tengo alguna lógica que debería ejecutarse cuando Activityrealmente se crea, no en cada cambio de orientación, solo ejecuto esa lógica onCreate()solo si savedInstanceStatees nula.

De lo contrario, todavía quiero que el diseño se vuelva a dibujar correctamente para la orientación.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

No estoy seguro si esta es la respuesta definitiva, pero funciona para mí.

nebulosas
fuente
66
¿Y dónde estás realmente guardando el estado?
Ewoks el
55
Esto parece funcionar para mí y parece, con mucho, el método más simple. Noté que solo obtuviste 4 ups para esto (5 incluidos los míos) frente a 373 para la idea sobre la subclasificación de aplicaciones, que para mí parece mucho más complicada. ¿Hay algún inconveniente en este método?
steveh
44
Esta solución funcionó GENIAL para mí. pude Intent serverintent = new Intent(MainActivity.this, MessageListener.class);y pude startService(serverintent);crear un serverSocket = new ServerSocket(0xcff2);y Socket client = serverSocket.accept();con a BufferedReader(new InputStreamReader(client.getInputStream()));y pude rotar mi Android y mantener activa la conexión cliente / servidor, pero hice girar la GUI. De acuerdo con el manual, savedInstanceState se inicializa cuando se cierra la última actividad.
Fred F
3
No entiendo, ¿cuál es el problema? Esto funciona muy bien y con mucha menos complejidad que cualquiera de las otras soluciones.
RTF
3
Esta es la forma correcta de hacerlo en Android. Las otras formas de capturar básicamente una rotación con configChanges y todo lo que es voluminoso, complejo e innecesario.
LukeWaggoner
99

lo que hice...

en el manifiesto, a la sección de actividad, agregó:

android:configChanges="keyboardHidden|orientation"

en el código de la actividad, implementado:

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}
Alguien en alguna parte
fuente
3
para aclarar: con mi implementación ahora puede tener una inicialización variable en onCreate () y onConfigurationChanged () simplemente se llamará para la rotación de la pantalla. Sus variables ahora están aisladas de las rotaciones de pantalla ;-) nice and ez
Someone Somewhere
2
Hice todo tal como se describe aquí, pero obtengo NullPointerException cuando intento presionar un botón después del cambio de orientación. ¿Qué podría estar mal?
Finnboy11
55
tenga en cuenta que mi respuesta es como hace 3 años y Android sigue evolucionando ... Simon: ¿tiene un enlace a un código de muestra? Eso es lo que la gente necesita.
Alguien en algún lugar
3
Cuando se advierte contra android: configChanges, @ SimonAndréForsberg en realidad solo está parafraseando los documentos de Android . Manejando cambios en tiempo de ejecución tiene información más detallada sobre las alternativas (incluido el código de muestra).
Leif Arne Storset 01 de
67

Lo que describe es el comportamiento predeterminado. Debe detectar y manejar estos eventos usted mismo agregando:

android:configChanges

a su manifiesto y luego los cambios que desea manejar. Entonces, para la orientación, usaría:

android:configChanges="orientation"

y para que el teclado se abra o cierre, usaría:

android:configChanges="keyboardHidden"

Si desea manejar ambos, puede separarlos con el comando de tubería como:

android:configChanges="keyboardHidden|orientation"

Esto activará el método onConfigurationChanged en cualquier actividad que llame. Si anula el método, puede pasar los nuevos valores.

Espero que esto ayude.

GregD
fuente
2
@GregD Lo sé, por eso ahora es un buen momento para actualizarlo para reflejar la situación actual. Dado el número de votos a favor que tiene esta pregunta, todavía se hace referencia a ella desde otras preguntas sobre SO.
Simon Forsberg el
48

Acabo de descubrir esta historia:

Para mantener viva la Actividad a través de un cambio de orientación y manejarla onConfigurationChanged, la documentación y el ejemplo de código anterior sugieren esto en el archivo de Manifiesto:

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

que tiene el beneficio adicional de que siempre funciona.

El conocimiento adicional es que omitir el keyboardHiddenpuede parecer lógico, pero causa fallas en el emulador (al menos para Android 2.1): especificar solo orientationhará que el emulador llame a ambas OnCreatey onConfigurationChanged, a veces, y solo OnCreateotras veces.

No he visto la falla en un dispositivo, pero he escuchado que el emulador falla para otros. Entonces vale la pena documentarlo.

Liudvikas Bukys
fuente
14
Precaución: a partir de Android 3.2 (API nivel 13), el "tamaño de la pantalla" también cambia cuando el dispositivo cambia entre orientación vertical y horizontal. Por lo tanto, si desea evitar que se reinicie el tiempo de ejecución debido al cambio de orientación al desarrollar para el nivel API 13 o superior: android: configChanges = "oriente | keyboardHidden | screenSize"
Geltrude
Sí, el emulador apesta a lo grande. No puede confiar en que informe los cambios de configuración con precisión.
IgorGanapolsky
Agregar android: configChanges solo debe usarse como último recurso . Considere usar Fragmentsy en su setRetainInstancelugar.
Simon Forsberg el
38

También puede considerar usar la forma en que la plataforma Android mantiene los datos en los cambios de orientación: onRetainNonConfigurationInstance()y getLastNonConfigurationInstance().

Esto le permite conservar los datos a través de los cambios de configuración, como la información que puede haber obtenido de una búsqueda del servidor o algo más que se ha calculado en onCreateo desde entonces, al tiempo que permite que Android rediseñe su Activityuso del archivo xml para la orientación que está ahora en uso .

Mira aquí o aquí .

Cabe señalar que estos métodos ahora están en desuso (aunque aún más flexible que la orientación del manejo, cambie usted mismo como sugiere la mayoría de las soluciones anteriores) con la recomendación de que todos cambien Fragmentsy usen setRetainInstance(true)en cada uno Fragmentque quieran conservar.

Jon O
fuente
3
Realmente creo que Fragments y setRetainInstance es la mejor manera (y recomendada por Google) para hacer esto, +1 para ti y -1 para todos los demás. Agregar Android: configChanges solo debe usarse como último recurso
Simon Forsberg
32

El enfoque es útil pero está incompleto cuando se usan Fragmentos.

Los fragmentos generalmente se recrean en el cambio de configuración. Si no desea que esto suceda, use

setRetainInstance(true); en los constructores del Fragmento

Esto hará que se retengan fragmentos durante el cambio de configuración.

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)

Abdo
fuente
77
Convenido. Con la última API de Android, parece que los Fragmentos son la forma correcta de manejar esto. Todavía no lo he probado, pero por lo que he reunido leyendo esta página , básicamente mueves el 99% de lo que solías implementar en una Actividad a una subclase de un Fragmento, luego agregas ese Fragmento a la Actividad. La actividad seguirá siendo destruida y recreada en la rotación de la pantalla, pero puedes decirle específicamente a Android que no destruya el Fragmento usando el setRetainInstance()método mencionado por @Abdo.
brianmearns
25

Simplemente agregué

     android:configChanges="keyboard|keyboardHidden|orientation"

en el archivo de manifiesto y no agregué ningún onConfigurationChangedmétodo en mi actividad.

Entonces, cada vez que el teclado se desliza hacia afuera o no sucede nada .

bass.t
fuente
agregado <application ...android:configChanges="keyboard|keyboardHidden|orientation">y está funcionando. Mi configuración en build.gradle:minSdkVersion 15, compileSdkVersion 23, buildToolsVersion "23.0.2"
Junior Mayhé
19

El onCreatemétodo todavía se llama incluso cuando cambias el orientationde android. Por lo tanto, mover todas las funciones pesadas a este método no te ayudará

Ganesh Krishnan
fuente
18

Ponga el siguiente código dentro de su <activity>etiqueta en Manifest.xml:

android:configChanges="screenLayout|screenSize|orientation"
Vaishali Sutariya
fuente
17
 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

¿Qué parte del manifiesto le dice "no llamar onCreate()"?

También, documentos de Google dicen a evitar el uso android:configChanges(excepto como último recurso) .... Pero entonces los métodos alternativos que sugieren todo DO uso android:configChanges.

Según mi experiencia, el emulador SIEMPRE llama onCreate()al girar.
Pero los dispositivos 1-2 en los que ejecuto el mismo código ... no lo hacen. (No estoy seguro de por qué habría alguna diferencia).

Villancico
fuente
16

Es muy simple solo siga los siguientes pasos:

<activity
    android:name=".Test"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="landscape" >
</activity>

Esto funciona para mi:

Nota: la orientación depende de su requerimiento

ManiTeja
fuente
15

Los cambios a realizar en el manifiesto de Android son:

android:configChanges="keyboardHidden|orientation" 

Las adiciones a realizar dentro de la actividad son:

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();
    }
}
pandemia sumit
fuente
15

Agregue esta línea a su manifiesto: -

android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"

y este fragmento de la actividad: -

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
Parin Parikh
fuente
14

Hay varias formas de hacerlo:

Guardar estado de actividad

Puede guardar el estado de la actividad en onSaveInstanceState.

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

y luego use bundlepara restaurar el estado.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

Maneja los cambios de orientación por ti mismo

Otra alternativa es manejar los cambios de orientación usted mismo. Pero esto no se considera una buena práctica.

Agregue esto a su archivo de manifiesto.

android:configChanges="keyboardHidden|orientation"

para Android 3.2 y posterior:

android:configChanges="keyboardHidden|orientation|screenSize"

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

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

Restringir rotación

También puede limitar su actividad al modo vertical u horizontal para evitar la rotación.

Agregue esto a la etiqueta de actividad en su archivo de manifiesto:

        android:screenOrientation="portrait"

O implemente esto programáticamente en su actividad:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Piyush
fuente
11

La forma en que he encontrado para hacer esto es usar el onRestoreInstanceStatey los onSaveInstanceStateeventos para guardar algo en el Bundle(incluso si no necesita guardar ninguna variable, simplemente coloque algo allí para Bundleque no esté vacío). Luego, en el onCreatemétodo, verifique si Bundleestá vacío, y si lo está, haga la inicialización, si no, hágalo.

Shaun
fuente
11

A pesar de que no es "la forma de Android", he obtenido muy buenos resultados manejando los cambios de orientación y simplemente reposicionando los widgets dentro de una vista para tener en cuenta la orientación alterada. Esto es más rápido que cualquier otro enfoque, ya que sus vistas no tienen que guardarse ni restaurarse. También proporciona una experiencia más fluida para el usuario, porque los widgets reposicionados son exactamente los mismos, simplemente movidos y / o redimensionados. No solo el estado del modelo, sino también el estado de vista, se pueden conservar de esta manera.

RelativeLayoutA veces puede ser una buena opción para una vista que tiene que reorientarse de vez en cuando. Simplemente proporcione un conjunto de parámetros de diseño de retrato y un conjunto de parámetros de diseño de paisaje, con diferentes reglas de posicionamiento relativo en cada uno, para cada widget secundario. Luego, en su onConfigurationChanged()método, pasa el apropiado a una setLayoutParams()llamada de cada niño. Si algún control secundario en sí mismo necesita ser reorientado internamente , simplemente llame a un método en ese elemento secundario para realizar la reorientación. Ese niño llama de manera similar a los métodos en cualquiera de sus controles secundarios que necesitan una reorientación interna, y así sucesivamente.

Carl
fuente
Me encantaría ver un código de muestra de esto, ¡parece genial!
Henrique de Sousa
8

Cada vez que se gira la pantalla, la actividad abierta finaliza y se vuelve a llamar a onCreate ().

1) Puede hacer una cosa, guardar el estado de la actividad cuando se gira la pantalla para que pueda recuperar todas las cosas viejas cuando se vuelve a llamar a onCreate () de la actividad. Consulte este enlace

2) Si desea evitar el reinicio de la actividad, simplemente coloque las siguientes líneas en su archivo manifest.xml.

  <activity android:name=".Youractivity"
  android:configChanges="orientation|screenSize"/>
Mansuu ....
fuente
7

debe usar el método onSavedInstanceState para almacenar todo el valor de su parámetro is has que es bundle

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

y use

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

para recuperar y establecer el valor para ver objetos, manejará las rotaciones de la pantalla

koteswara DK
fuente
Esto necesita API nivel 22.
Mohammad Afrashteh
6

Nota: publico esta respuesta si alguien en el futuro enfrenta el mismo problema que yo. Para mí, la siguiente línea no fue suficiente:

android:configChanges="orientation"

Cuando roté la pantalla, no se llamó al método `onConfigurationChanged (Configuration newConfig).

Solución: también tuve que agregar "screenSize" incluso si el problema tenía que ver con la orientación. Entonces, en el archivo AndroidManifest.xml, agregue esto:

android:configChanges="keyboardHidden|orientation|screenSize"

Luego implemente el método onConfigurationChanged(Configuration newConfig)

iHank
fuente
5

En la sección de actividades del manifest, agregue:

android:configChanges="keyboardHidden|orientation"
Richard K Maleho
fuente
5

Agregue esta línea en manifiesto: android:configChanges="orientation|screenSize"

Vikramsinh Gaikwad
fuente
4

La gente dice que deberías usar

android:configChanges="keyboardHidden|orientation"

Pero la mejor y más profesional forma de manejar la rotación en Android es usar la clase Loader. No es una clase famosa (no sé por qué), pero es mucho mejor que AsyncTask. Para obtener más información, puede leer los tutoriales de Android que se encuentran en los cursos de Android de Udacity.

Por supuesto, como otra forma, puede almacenar los valores o las vistas con onSaveInstanceState y leerlos con onRestoreInstanceState. Depende de ti realmente.

Theo
fuente
Sí, agreguemos montones de código extra para parecer "profesional". ¿O qué tal si simplemente se apega a la forma rápida, fácil, verdadera y probada de hacerlo con el atributo configurationChanges?
AndroidDev
3

Después de un tiempo de prueba y error, encontré una solución que se adapta a mis necesidades en la mayoría de las situaciones. Aquí está el código:

Configuración manifiesta:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.pepperonas.myapplication">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

Actividad principal:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private Fragment mFragment;

    private int mSelected = -1;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate  " + "");

        // null check not realy needed - but just in case...
        if (savedInstanceState == null) {

            initUi();

            // get an instance of FragmentTransaction from your Activity
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            /*IMPORTANT: Do the INITIAL(!) transaction only once!
            * If we call this everytime the layout changes orientation,
            * we will end with a messy, half-working UI.
            * */
            mFragment = FragmentOne.newInstance(mSelected = 0);
            fragmentTransaction.add(R.id.frame, mFragment);
            fragmentTransaction.commit();
        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged  " +
                   (newConfig.orientation
                    == Configuration.ORIENTATION_LANDSCAPE
                    ? "landscape" : "portrait"));

        initUi();

        Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
        makeFragmentTransaction(mSelected);
    }


    /**
     * Called from {@link #onCreate} and {@link #onConfigurationChanged}
     */
    private void initUi() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
        Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
        Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
        btnFragmentOne.setOnClickListener(this);
        btnFragmentTwo.setOnClickListener(this);
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume  " + "");
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause  " + "");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy  " + "");
    }


    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btn_fragment_one:
                Log.d(TAG, "onClick btn_fragment_one " + "");
                makeFragmentTransaction(0);
                break;

            case R.id.btn_fragment_two:
                Log.d(TAG, "onClick btn_fragment_two " + "");
                makeFragmentTransaction(1);
                break;

            default:
                Log.d(TAG, "onClick  null - wtf?!" + "");
        }
    }


    /**
     * We replace the current Fragment with the selected one.
     * Note: It's called from {@link #onConfigurationChanged} as well.
     */
    private void makeFragmentTransaction(int selection) {

        switch (selection) {
            case 0:
                mFragment = FragmentOne.newInstance(mSelected = 0);
                break;
            case 1:
                mFragment = FragmentTwo.newInstance(mSelected = 1);
                break;
        }

        // Create new transaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.frame, mFragment);

        /*This would add the Fragment to the backstack...
        * But right now we comment it out.*/
        //        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

}

Y muestra Fragmento:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Martin Pfeffer (pepperonas)
 */
public class FragmentOne extends Fragment {

    private static final String TAG = "FragmentOne";


    public static Fragment newInstance(int i) {
        Fragment fragment = new FragmentOne();
        Bundle args = new Bundle();
        args.putInt("the_id", i);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView  " + "");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }

}

Se puede encontrar en github .

Martin Pfeffer
fuente
3

Use el orientationoyente para realizar diferentes tareas en diferentes orientaciones.

@Override
public void onConfigurationChanged(Configuration myConfig) 
{
    super.onConfigurationChanged(myConfig);
    int orient = getResources().getConfiguration().orientation; 
    switch(orient) 
    {
       case Configuration.ORIENTATION_LANDSCAPE:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
       case Configuration.ORIENTATION_PORTRAIT:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
       default:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
}
Akshay Paliwal
fuente
3

Poner este código en su continuación Activityen Android Manifest.

android:configChanges="orientation"

Esto no reiniciará su actividad cuando cambie la orientación.

Pratik Dasa
fuente
2
@Mavamaarten Probablemente porque, como otros han señalado, es una mala práctica y otras diez respuestas ya han cubierto esto.
MikkoP
3

Fijar la orientación de la pantalla (horizontal o vertical) en AndroidManifest.xml

android:screenOrientation="portrait" o android:screenOrientation="landscape"

para esto onResume()no se llama su método.

Brajendra Pandey
fuente
55
¿Cómo demonios arreglar algo es una respuesta? ¿Por qué pueden rotar nuestros dispositivos si bloqueamos a los usuarios que lo usan?
Reinherd
3

Uno de los mejores componentes del android architechure introducido por google cumplirá con todos los requisitos que tiene ViewModel.

Está diseñado para almacenar y administrar datos relacionados con la interfaz de usuario en el ciclo de vida, además de que permitirá que los datos sobrevivan a medida que la pantalla gira

class MyViewModel : ViewModel() {

Consulte esto: https://developer.android.com/topic/libraries/architecture/viewmodel

Android Geek
fuente