studio rotación rotacion reinicio reinicie que pantalla orientacion movil manejando girar evitar detectar configchanges como cambio bloquear activity android rotation android-activity

rotacion - Actividad reinicio en rotación Android



manejando la rotación de pantalla en android studio (30)

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 dice "no llamar a onCreate() "?

Además, los documentos de Google dicen que se debe evitar el uso de android:configChanges (excepto como último recurso) ... Pero luego, los métodos alternativos que sugieren todos usan el android:configChanges .

Ha sido mi experiencia que el emulador SIEMPRE llama onCreate() en la rotación.
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).

En mi aplicación de Android, cuando giro el dispositivo ( onCreate el teclado), se reinicia mi Activity (se llama onCreate ). Ahora, probablemente es así como se supone que debe ser, pero hago mucha configuración inicial en el método onCreate , así que necesito:

  1. Coloque toda la configuración inicial en otra función para que no se pierda todo en la rotación del dispositivo o
  2. Asegúrese de que onCreate no se vuelva a llamar y el diseño simplemente se ajusta o
  3. Limite la aplicación a solo retrato para que no se llame a onCreate .

Añade esta línea a tu 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); }


Acabo de descubrir esta historia

Para mantener viva la Actividad a través de un cambio de orientación, y manejarla 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 de que siempre funciona.

La experiencia adicional es que omitir el keyboardHidden Oculto puede parecer lógico, pero causa fallas en el emulador (al menos para Android 2.1): especificar solo la orientation hará que el emulador llame a OnCreate y onConfigurationChanged , y solo a OnCreate otras veces.

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


Actualización para Android 3.2 y superior:

Precaución : A partir de Android 3.2 (nivel de API 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 a un cambio de orientación al desarrollar para API nivel 13 o superior (según lo declarado por los atributos minSdkVersion y targetSdkVersion), debe incluir el valor "screenSize" además del valor de "orientation" . Es decir, debe 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 (este cambio de configuración no reinicia su actividad, incluso cuando se ejecuta en un dispositivo Android 3.2 o superior).


Agregue esta línea android: configChanges = "orientación | tamaño de pantalla" en el manifiesto


Aunque no es "a la manera de Android", he obtenido muy buenos resultados al manejar los cambios de orientación y simplemente reposicionando los widgets dentro de una vista para tener en cuenta la orientación modificada. 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, ya que los widgets reposicionados son exactamente los mismos widgets, solo se han movido y / o han cambiado de tamaño. No solo 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 debe reorientarse de vez en cuando. Solo proporciona un conjunto de parámetros de diseño vertical y un conjunto de parámetros de diseño paisajístico, con diferentes reglas de posicionamiento relativo en cada uno, para cada widget secundario. Luego, en tu método onConfigurationChanged() , pasas el apropiado a una llamada a setLayoutParams() en cada hijo. Si cualquier control secundario necesita ser reorientado internamente , simplemente llame a un método para que realice la reorientación. De manera similar, ese niño llama a los métodos de cualquiera de sus controles secundarios que necesitan reorientación interna, y así sucesivamente.


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

1. Puede hacer una cosa, guardar el estado de actividad cuando se gira la pantalla, de modo que, puede recuperar todas las cosas antiguas cuando se vuelve a llamar a onCreate () de la actividad. Consulte this 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"/>


Coloque el código debajo de su etiqueta <activity> en Manifest.xml :

android:configChanges="screenLayout|screenSize|orientation"


Corrija 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() .


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 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 fragmento de muestra:

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 .



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

android:configChanges="keyboardHidden|orientation"


En lugar de intentar evitar que el onCreate() se dispare por completo, intente verificar que el Bundle savedInstanceState se transfiera al evento para ver si es nulo o no.

Por ejemplo, si tengo alguna lógica que debería ejecutarse cuando se crea realmente la Activity , no en cada cambio de orientación, solo ejecuto esa lógica en onCreate() solo 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í.


Es muy sencillo solo haz 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 requerimiento.


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

Maneja los cambios de orientación por ti mismo.

Otra alternativa es manejar los cambios de orientación por ti 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 rotación

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

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

android:screenOrientation="portrait"

O implementa esto programáticamente en tu actividad:

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


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


La gente dice que debes 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, de otra manera, puede almacenar los valores o las vistas con onSaveInstanceState y leerlos con onRestoreInstanceState Depende de usted realmente.


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

android:configChanges

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

android:configChanges="orientation"

y para el teclado que se está abriendo o cerrando usaría:

android:configChanges="keyboardHidden"

Si desea manejar ambos, puede simplemente 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.


Los cambios que se harán en el manifiesto de Android son:

android:configChanges="keyboardHidden|orientation"

Las adiciones que se harán 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(); } }


Pon este código debajo de tu Activity en Android Manifest .

android:configChanges="orientation"

Esto no reiniciará tu actividad cuando cambies de orientación.


Se onCreate método onCreate incluso cuando cambias la orientation de Android. Así que mover toda la funcionalidad pesada a este método no te ayudará.



También podría considerar el uso de la forma de la plataforma Android de persistir los datos en los cambios de orientación: onRetainNonConfigurationInstance() y getLastNonConfigurationInstance() .

Esto le permite conservar los datos en 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 haya computado en onCreate o desde entonces, mientras que también permite que Android vuelva a diseñar su Activity utilizando el archivo xml para la orientación actual. en uso.

Ver here o aquí .

Debe tenerse en cuenta que estos métodos ahora están en desuso (aunque aún son más flexibles que la orientación por sí mismos, cambie como lo 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 desee conservar .


Utilice la escucha de orientation para realizar diferentes tareas en orientación diferente.

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


lo que hice...

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

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


necesita usar el método onSavedInstanceState para almacenar todo el valor para que su parámetro sea tiene ese 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 manejará las rotaciones de la pantalla


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 giré la pantalla, el método `onConfigurationChanged (Configuration newConfig) no fue llamado.

Solución: También tuve que agregar "tamaño de pantalla" incluso si el problema tenía que ver con la orientación. Entonces, en el archivo AndroidManifest.xml, agrega esto:

android:configChanges="keyboardHidden|orientation|screenSize"

Luego implemente el método onConfigurationChanged(Configuration newConfig)


Usando la clase de aplicación

Dependiendo de lo que esté haciendo en su inicialización, podría considerar crear una nueva clase que extienda la Application y mover su código de inicialización a un método onCreate anulado 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 solo se llama cuando se crea la aplicación completa, por lo que la Actividad se reinicia en la orientación o los cambios en la 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 la aplicación que está inicializando utilizando captadores y definidores.

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"

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

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

Comience agregando el nodo android:configChanges nodo manifiesto de su actividad

android:configChanges="keyboardHidden|orientation"

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

android:configChanges="keyboardHidden|orientation|screenSize"

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

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


Puede bloquear la orientación actual de la pantalla usando este código ...

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


Puedes usar el objeto ViewModel en tu actividad.

Los objetos de ViewModel se retienen automáticamente durante los cambios de configuración, de modo que los datos que contienen están inmediatamente disponibles para la siguiente actividad o instancia de fragmento. Lee mas:

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