Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Actividad de reinicio en la rotación de Android

En mi aplicación Android, cuando hago girar el dispositivo (deslice el teclado), se reinicia mi Activity ( onCreate se llama). Ahora, esto es probablemente como se supone que es, pero hago un montón de configuración inicial en el método onCreate , por lo que necesito:

  1. Coloque todos los ajustes iniciales en otra función para que no se pierdan todos en la rotación del dispositivo o
  2. Hacer tan onCreate no se llama de nuevo y el diseño sólo se ajusta o
  3. Limite la aplicación a un retrato para que onCreate no se llame.

  • ¿Cómo puedo configurar una sombra en cada celda de un ListView?
  • LinearLayout analógico dentro de la tabla en LibGDX
  • Cómo agregar la misma vista a los padres varias veces inflando sólo una vez
  • ¿Cómo configurar el TimePickerDialog a 24 horas?
  • Cómo deshabilitar onItemSelectedListener que se invocará al configurar el elemento seleccionado por código
  • ¿La mejor manera de detectar si el texto de TextView ha sido cambiado?
  • Cómo crear un motor de texto a voz personalizado
  • Adb extraer varios archivos
  • El seguimiento de referencias de Android no funciona
  • ¿Hay un detector de llamadas interrumpidas
  • Unparsed aapt error (s)!
  • Android Wear Error ConnectionResult {statusCode = SERVICE_VERSION_UPDATE_REQUIRED, resolution = null}
  • 27 Solutions collect form web for “Actividad de reinicio en la rotación de Android”

    Uso de la clase de aplicación

    Dependiendo de lo que esté haciendo en su inicialización, podría considerar la posibilidad de crear una nueva clase que amplíe la Application y mueva el código de inicialización en un método onCreate sobreescrito dentro de esa clase.

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

    El onCreate en la clase de aplicación sólo se llama cuando se crea toda la aplicación, 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 para exponer la instancia de esta clase como singleton y exponer las variables de la aplicación que está inicializando mediante getters y setters.

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

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

    Reaccionar a los cambios de configuración [UPDATE: se desaconseja desde API 13; Vea la alternativa recomendada ]

    Como otra alternativa, puede hacer que su aplicación escuche eventos que causen una orientación similar a la reinicialización y cambios en la visibilidad del teclado – y manejarlos dentro de su Actividad.

    Comienza añadiendo el nodo android:configChanges nodo de manifiesto de tu actividad

     android:configChanges="keyboardHidden|orientation" 

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

     android:configChanges="keyboardHidden|orientation|screenSize" 

    A continuación, dentro de la Actividad, sustituya el método onConfigurationChanged y llame a setContentView para forzar el diseño de GUI que se vuelva a realizar en la nueva orientación.

     @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); setContentView(R.layout.myLayout); } 

    Actualización para Android 3.2 y versiones superiores:

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

    En lugar de tratar de detener el onCreate() de ser disparado por completo, tal vez intente comprobar el Bundle savedInstanceState se pasa en el evento para ver si es nulo o no.

    Por ejemplo, si tengo alguna lógica que debería ser ejecutada cuando la Activity es verdaderamente creada, no en cada cambio de orientación, sólo ejecuto esa lógica en el onCreate() sólo si el savedInstanceState es nulo.

    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 de si esta es la respuesta definitiva, pero funciona para mí.

    lo que hice…

    En el manifiesto, a la sección de actividad, añadió:

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

    Lo que usted describe es el comportamiento predeterminado. Tienes que detectar y manejar estos eventos tú mismo añadiendo:

     android:configChanges 

    A su manifiesto y luego a los cambios que desea manejar. Así que para la orientación, usted utilizaría:

     android:configChanges="orientation" 

    Y para el teclado que se abre o se cierra utilizaría:

     android:configChanges="keyboardHidden" 

    Si quieres manejar ambos puedes separarlos con el comando pipe como:

     android:configChanges="keyboardHidden|orientation" 

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

    Espero que esto ayude.

    Acabo de descubrir esta sabiduría:

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

     android:configChanges="keyboardHidden|orientation" 

    Que tiene el beneficio extra que siempre funciona.

    El lore de la prima es que omitir el keyboardHidden puede parecer lógico, pero causa fallas en el emulador (para Android 2.1 por lo menos): especificando solamente la orientation hará que el emulador llama OnCreate y onConfigurationChanged veces, y solamente OnCreate otras veces.

    No he visto el fallo en un dispositivo, pero he oído sobre el emulador fallando para otros. Así que vale la pena documentar.

    También puede considerar el uso de la forma de la plataforma Android de datos persistentes a través de los cambios de orientación: onRetainNonConfigurationInstance() y getLastNonConfigurationInstance() .

    Esto le permite persistir los datos a través de los cambios de configuración, como la información que puede haber obtenido de una búsqueda de servidor o algo que se ha calculado en onCreate o desde, al tiempo que también permite a Android para volver a diseñar su Activity utilizando el archivo xml para la orientación ahora en uso.

    Vea aquí o aquí .

    Debe tenerse en cuenta que estos métodos están ahora obsoletos (aunque aún más flexible que el manejo de la orientación cambie usted mismo como sugieren la mayoría de las soluciones anteriores) con la recomendación de que todos cambien a Fragments y utilicen setRetainInstance(true) en cada Fragment que desea retener .

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

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

    setRetainInstance(true); En el (los) constructor (es) del Fragmento

    Esto hará que los fragmentos sean retenidos durante el cambio de configuración.

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

    Acabo de agregar simplemente

      android:configChanges="keyboard|keyboardHidden|orientation" 

    En el archivo de manifiesto y no agregó ningún método onConfigurationChanged en mi actividad.

    Así que cada vez que el teclado se desliza o no ocurre nada .

      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 onCreate() "?

    Además, los documentos de Google dicen para evitar el uso de android:configChanges (excepto como último recurso) …. Pero, a continuación, los métodos alternativos que sugieren todos los DO utilizar android:configChanges .

    Ha sido mi experiencia que el emulador siempre llama onCreate() en rotación.
    Pero los dispositivos 1-2 que ejecutar el mismo código en … no. (No estoy seguro de por qué habría diferencia.)

    Los cambios que se realizarán 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(); } } 

    Añada 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); } 

    La forma en que he encontrado que hacer esto es usar los onRestoreInstanceState y onSaveInstanceState para guardar algo en el Bundle (incluso si no necesita ninguna variable guardada, solo coloque algo allí para que el Bundle no esté vacío). Luego, en el método onCreate , compruebe si el Bundle está vacío, y si es así, haga la inicialización, si no, entonces hágalo.

    El método onCreate se llama aún cuando cambia la orientation de android. Así que mover toda la funcionalidad pesada a este método no va a ayudarte

    A pesar de que no es "la forma de Android" he conseguido muy buenos resultados al manejar los cambios de orientación yo mismo y simplemente reposicionar 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 ser guardadas y restauradas. También proporciona una experiencia más perfecta para el usuario, porque los widgets reposicionados son exactamente los mismos widgets, simplemente movidos y / o redimensionados. No sólo el estado del modelo, sino también el estado de la vista, se pueden conservar de esta manera.

    RelativeLayout 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 ajardinados, con diferentes reglas de posicionamiento relativo en cada uno, para cada widget secundario. Entonces, en su método onConfigurationChanged() , usted pasa el apropiado a una llamada de setLayoutParams() en cada niño. Si cualquier control del niño necesita ser internamente reorientado, simplemente llame a un método en ese niño para realizar la reorientación. Ese niño de manera similar llama métodos a cualquiera de sus controles de niño que necesitan una reorientación interna, y así sucesivamente.

    Es muy simple hacer los siguientes pasos:

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

    Esto funciona para mí:

    Nota: la orientación depende de su requitement

    Hay varias formas de hacer esto:

    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 usar el bundle para 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 } } 

    Maneje los cambios de orientación por sí mismo

    Otra alternativa es manejar los cambios de orientación por 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 versiones posteriores:

     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 la rotación

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

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

      android:screenOrientation="portrait" 

    O implementarlo de forma programática en su actividad:

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

    Ponga debajo del código dentro de su etiqueta <activity> en Manifest.xml

    Android: configChanges = "screenLayout | screenSize | orientación"

    Nota: publicar esta respuesta si alguien en el futuro se enfrentan al mismo problema que yo. Para mí la siguiente línea no era suficiente:

     android:configChanges="orientation" 

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

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

     android:configChanges="keyboardHidden|orientation|screenSize" 

    A continuación, implemente el método onConfigurationChanged(Configuration newConfig)

    Cada vez que se gira la pantalla, la actividad abierta se termina y onCreate () se llama de nuevo.

    1. Usted puede hacer una cosa excepto el estado de la actividad cuando se gira la pantalla de modo que, usted pueda recuperar todas las cosas viejas cuando onCreate de la actividad () se llama otra vez. Referir este enlace

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

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

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

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

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

    Usted necesita utilizar el método onSavedInstanceState para almacenar todo el valor a su parámetro es tiene que es paquete

     @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 los objetos que se encargará de las rotaciones de la pantalla

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

     android:configChanges="keyboardHidden|orientation" 

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

    Configuración del manifiesto:

     <?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 .

    Utilice el detector de orientation 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); } } 

    Ponga este código debajo en su Activity in Android Manifest .

     android:configChanges="orientation" 

    Esto no reiniciará su actividad cuando cambiaría la orientación.

    You can lock to the current orientation of screen using this code…

     int currentOrientation =context.getResources().getConfiguration().orientation; if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) { ((Activity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { ((Activity) context). setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.