rotación - rotacion de pantalla android studio




Actividad reinicio en rotación Android (20)

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

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


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"

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


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.


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.



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 .


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


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




android-activity