web-dev-qa-db-fra.com

Comment conserver les données EditText lors d'un changement d'orientation?

J'ai un écran de connexion qui se compose de 2 EditTexts pour le nom d'utilisateur et le mot de passe. Mon exigence est que lors d'un changement d'orientation, les données d'entrée (le cas échéant) dans EditText doivent rester telles quelles et une nouvelle mise en page doit également être dessinée. J'ai 2 fichiers xml de mise en page - un dans le dossier de mise en page et d'autres dans le dossier layout-land. J'essaie de mettre en œuvre les deux approches suivantes, mais aucune n'est parfaite:

(1) configChanges: keyboardHidden - Dans cette approche, je ne fournis pas "d'orientation" dans configChanges dans le fichier manifeste. J'appelle donc la méthode setContentView () dans les méthodes onCreate () et onConfigurationChanged (). Il répond à mes deux exigences. La disposition est modifiée et les données d'entrée dans EditTexts restent également telles quelles. Mais il a un gros problème:

Lorsque l'utilisateur clique sur le bouton de connexion, un ProgressDialog affiche jusqu'à ce que la réponse du serveur soit reçue. Maintenant, si l'utilisateur fait pivoter l'appareil pendant que ProgressDialog est en cours d'exécution, l'application se bloque. Il montre une exception indiquant "La vue ne peut pas être attachée à la fenêtre". J'ai essayé de le gérer en utilisant onSaveInstanceState (qui est appelé lors du changement d'orientation) mais l'application se bloque toujours.

(2) configChanges: orientation | keyboardHidden - Dans cette approche, je fournis "orientation" dans le manifeste. Alors maintenant, j'ai 2 scénarios:

(a) Si j'appelle la méthode setContentView () dans onCreate () et onConfigurationChanged (), la disposition est modifiée en conséquence mais les données EditText sont perdues.

(b) Si j'appelle la méthode setContentView () dans onCreate (), mais pas dans onConfigurationChanged (), les données EditText ne sont pas perdues mais la disposition ne change pas non plus en conséquence.

Et dans cette approche, onSaveInstanceState () n'est même pas appelé.

Je suis donc dans une situation vraiment intimidante. Y-a t'il une solution à ce problème? Veuillez aider. Merci d'avance.

29
Yogesh Somani

dans la méthode onConfigurationChanged, obtenez d'abord les données des deux textes d'édition dans des variables globales, puis appelez la méthode setContentView. Maintenant, définissez à nouveau les données enregistrées dans les textes d'édition.

9
Arpit Raniwala

Par défaut, Edittext enregistre sa propre instance lors du changement d'orientation.

Assurez-vous que les 2 Edittexts ont des ID uniques et ont les mêmes ID dans les deux mises en page.

De cette façon, leur état doit être enregistré et vous pouvez laisser Android gérer le changement d'orientation.

Si vous utilisez un fragment, assurez-vous qu'il possède également un ID unique et que vous ne le recréez pas lors de la recréation de l'activité.

81
Yalla T.

Une meilleure approche consiste à laisser Android gérer le changement d'orientation. Android récupérera automatiquement la mise en page du bon dossier et l'affichera à l'écran. Tout ce dont vous avez besoin faire consiste à enregistrer les valeurs d'entrée des textes méthode onSaveInsanceState () et utilisez ces valeurs enregistrées pour initialiser les textes d'édition dans le méthode onCreate ().
Voici comment vous pouvez y parvenir:

@Override
protected void onCreate (Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.login_screen);
    ...
    ...
    String userName, password;
    if(savedInstanceState!=null)
    {
        userName = savedInstanceState.getString("user_name");
        password= savedInstanceState.getString("password");
    }

    if(userName != null)
        userNameEdtTxt.setText(userName);
    if(password != null)
        passEdtTxt.setText(password);
}

>

@Override
    protected void onSaveInstanceState (Bundle outState)
    {
        outState.putString("user_name", userNameEdtTxt.getText().toString());
        outState.putString("password",  passEdtTxt.getText().toString());
    }
33
karn

Il existe plusieurs façons de procéder. Le plus simple est 2(b) dans votre question. Mentionnez Android:configChanges="orientation|keyboardHidden|screenSize" Dans votre manifeste afin que l'activité ne soit pas détruite lors des changements d'orientation.

Appelez setContentView() dans onConfigChange(). mais avant d'appeler setContentView (), récupérez les données EditText dans une chaîne et réinitialisez-les après avoir appelé setContentView()

 @Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mEditTextData = mEditText.getText().tostring();//mEditTextData is a String 
                                                   //member variable
    setContentView(R.layout.myLayout);
    initializeViews();
}

private void initializeViews(){
    mEditText = (EditText)findViewById(R.id.edittext1);
    mEdiText.setText(mEditTextData);
}
3
sujith

Im restaurer l'instance pour restaurer les valeurs et cela fonctionne bien pour moi :)

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.addtask2);
    if(savedInstanceState!=null)
     onRestoreInstanceState(savedInstanceState);

}
2
Aswin Anand

Ce qui suit devrait fonctionner et est standard pour les activités et les fragments

@Override
public void onSaveInstanceState (Bundle outState) 
{
     outState.putString("editTextData1", editText1.getText().toString());
     outState.putString("editTextData2", editText2.getText().toString());

     super.onSaveInstanceState(outState);
}

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

      ... find references to editText1, editText2

      if (savedInstanceState != null)
      {
           editText1.setText(savedInstanceState.getString("editTextData1");
           editText2.setText(savedInstanceState.getString("editTextData2");
      }
}
2
chris-tulip

enter image description here

Saving state = Saving (Fragment State + Activity State)

Quand il s'agit de sauvegarder l'état d'un fragment lors d'un changement d'orientation, je procède généralement de cette façon.

1) État du fragment:

Enregistrer et restaurer la valeur EditText

// Saving State

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("USER_NAME", username.getText().toString());
    outState.putString("PASSWORD", password.getText().toString());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.user_name_fragment, parent, false);

    username = (EditText) view.findViewById(R.id.username);
    password = (EditText) view.findViewById(R.id.password);


// Retriving value

    if (savedInstanceState != null) {
        username.setText(savedInstanceState.getString("USER_NAME"));
        password.setText(savedInstanceState.getString("PASSWORD"));
    }

    return view;
}

2) État d'activité: :

Créez une nouvelle instance lorsque l'activité est lancée pour la première fois. Trouvez l'ancien fragment à l'aide d'une balise [~ # ~] [~ # ~] et du FragmentManager

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    fragmentManager = getSupportFragmentManager();

    if(savedInstanceState==null) {
        userFragment = UserNameFragment.newInstance();
        fragmentManager.beginTransaction().add(R.id.profile, userFragment, "TAG").commit();
    }
    else {
        userFragment = fragmentManager.findFragmentByTag("TAG");
    }

}

Vous pouvez voir le code de travail complet ICI

1
Rohit Singh

Comme l'a souligné Yalla T, il est important de ne pas recréer le fragment. EditText ne perdra pas son contenu si le fragment existant est réutilisé.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContentView(R.layout.activity_frame);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    // Display the fragment as the main content.
    // Do not do this. It will recreate the fragment on orientation change!
    // getSupportFragmentManager().beginTransaction().replace(Android.R.id.content, new Fragment_Places()).commit();

    // Instead do this
    String fragTag = "fragUniqueName";
    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = (Fragment) fm.findFragmentByTag(fragTag);
    if (fragment == null)
        fragment = new Fragment_XXX(); // Here your fragment
    FragmentTransaction ft = fm.beginTransaction();
    // ft.setCustomAnimations(R.xml.anim_slide_in_from_right, R.xml.anim_slide_out_left,
    // R.xml.anim_slide_in_from_left, R.xml.anim_slide_out_right);
    ft.replace(Android.R.id.content, fragment, fragTag);
    // ft.addToBackStack(null); // Depends on what you want to do with your back button
    ft.commit();

}
1
Gunnar Bernstein

Supprimez l'attribut Android: configChanges du fichier menifest et laissez Android gérer l'orientation changer vos données dans edittext restera automatiquement.

Maintenant, le problème que vous avez mentionné est lié à la fermeture forcée de la boîte de dialogue de progression, car lorsque l'orientation est modifiée, le thread s'exécutant dans backgroud tente de mettre à jour l'ancien composant de dialogue qui était visible. Vous pouvez le gérer en fermant la boîte de dialogue sur la méthode savedinstancestate et en rappelant le processus que vous souhaitez effectuer sur la méthode onRestoreInstanceState.

Voici un exemple d'espoir qu'il vous aidera à résoudre votre problème: -

public class MyActivity extends Activity {
    private static final String TAG = "com.example.handledataorientationchange.MainActivity";
    private static ProgressDialog progressDialog;
    private static Thread thread;
    private static boolean isTaskRunnig;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new EditText.OnClickListener() {

            @Override
            public void onClick(View v) {
                perform();
                isTaskRunnig = true;
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void perform() {
        Log.d(TAG, "perform");
        progressDialog = Android.app.ProgressDialog.show(this, null,
                "Working, please wait...");
        progressDialog
                .setOnDismissListener(new DialogInterface.OnDismissListener() {

                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        //isTaskRunnig = false;
                    }
                });
        thread = new Thread() {
            public void run() {
                Log.d(TAG, "run");
                int result = 0;
                try {

                    // Thread.sleep(5000);
                    for (int i = 0; i < 20000000; i++) {

                    }
                    result = 1;
                    isTaskRunnig = false;
                } catch (Exception e) {
                    e.printStackTrace();
                    result = 0;
                }
                Message msg = new Message();
                msg.what = result;
                handler.sendMessage(msg);
            };
        };
        thread.start();
    }

    // handler to update the progress dialgo while the background task is in
    // progress
    private static Handler handler = new Handler() {

        public void handleMessage(Message msg) {
            Log.d(TAG, "handleMessage");
            int result = msg.what;
            if (result == 1) {// if the task is completed successfully
                Log.d(TAG, "Task complete");
                try {
                    progressDialog.dismiss();
                } catch (Exception e) {
                    e.printStackTrace();
                    isTaskRunnig = true;
                }

            }

        }
    };

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onRestoreInstanceState" + isTaskRunnig);
        if (isTaskRunnig) {
            perform();

        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState");
        if (thread.isAlive()) {
            thread.interrupt();
            Log.d(TAG, thread.isAlive() + "");
            progressDialog.dismiss();
        }

    }
1
Chandrashekhar