98 votes

Empêcher le rejet de la boîte de dialogue en cas de rotation de l'écran dans Android

J'essaie d'empêcher les boîtes de dialogue construites avec Alert builder d'être rejetées lorsque l'activité est redémarrée.

Si je surcharge la méthode onConfigurationChanged, je peux le faire avec succès et réinitialiser la mise en page à l'orientation correcte, mais je perds la fonction de texte collant de l'edittext. Ainsi, en résolvant le problème du dialogue, j'ai créé ce problème d'edittext.

Si je sauvegarde les chaînes de caractères du texte d'édition et que je les réaffecte dans le changement d'onCofiguration, elles semblent toujours avoir la valeur initiale par défaut et non celle qui a été saisie avant la rotation. Même si je force une invalidation, cela semble les mettre à jour.

J'ai vraiment besoin de résoudre soit le problème du dialogue, soit celui de l'édition du texte.

Merci pour votre aide.

1 votes

Comment enregistrer/restaurer le contenu de l'EditText modifié ? Pouvez-vous montrer un peu de code ?

0 votes

J'ai compris le problème, j'avais oublié de récupérer la vue par Id après avoir réinitialisé la mise en page.

140voto

Brais Gabin Points 1284

Le meilleur moyen d'éviter ce problème aujourd'hui est d'utiliser une DialogFragment .

Créez une nouvelle classe qui étend DialogFragment . Remplacer onCreateDialog et rendez votre ancien Dialog ou un AlertDialog .

Ensuite, vous pouvez le montrer avec DialogFragment.show(fragmentManager, tag) .

Voici un exemple avec un Listener :

public class MyDialogFragment extends DialogFragment {

    public interface YesNoListener {
        void onYes();

        void onNo();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (!(activity instanceof YesNoListener)) {
            throw new ClassCastException(activity.toString() + " must implement YesNoListener");
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
                .setTitle(R.string.dialog_my_title)
                .setMessage(R.string.dialog_my_message)
                .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((YesNoListener) getActivity()).onYes();
                    }
                })
                .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((YesNoListener) getActivity()).onNo();
                    }
                })
                .create();
    }
}

Et dans l'activité que vous appelez :

new MyDialogFragment().show(getSupportFragmentManager(), "tag"); // or getFragmentManager() in API 11+

Cette réponse permet d'expliquer ces trois autres questions (et leurs réponses) :

0 votes

Il y a un bouton dans mon application qui appelle .show(), je dois me souvenir de l'état de la boîte de dialogue d'alerte, affichée/désactivée. Existe-t-il un moyen de conserver le dialogue sans appeler .show() ?

1 votes

Il est dit que onAttach est maintenant déprécié. Que faut-il faire à la place ?

3 votes

@faraz_ahmed_kamran, vous devriez utiliser onAttach(Context context) y android.support.v4.app.DialogFragment . Le site onAttach La méthode prend context au lieu de activity comme paramètre maintenant.

49voto

Chung IW Points 497
// Prevent dialog dismiss when orientation changes
private static void doKeepDialog(Dialog dialog){
    WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
    lp.copyFrom(dialog.getWindow().getAttributes());
    lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
    lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
    dialog.getWindow().setAttributes(lp);
}

public static void doLogout(final Context context){     
        final AlertDialog dialog = new AlertDialog.Builder(context)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setTitle(R.string.titlelogout)
        .setMessage(R.string.logoutconfirm)
        .setPositiveButton("Yes", new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                ...   
            }

        })
        .setNegativeButton("No", null)      
        .show();    

        doKeepDialog(dialog);
    }

1 votes

Pour ceux qui ne trouvent pas mon code utile, essayez-le avant de cliquer :-)

6 votes

Ça marche, je ne sais pas comment mais ça marche ! Une solution propre, simple et abstraite, merci.

1 votes

Solution étonnante, très simple contrairement aux autres solutions que j'ai trouvées, merci beaucoup, vous m'avez aidé à empêcher mon application de planter et avez résolu un bug crucial !!!

5voto

Maria Neumayer Points 2357

Si vous changez la mise en page lors d'un changement d'orientation, je ne mettrais pas android:configChanges="orientation" dans votre manifeste parce que vous recréez les vues de toute façon.

Sauvegardez l'état actuel de votre activité (comme le texte saisi, le dialogue affiché, les données affichées, etc.) en utilisant ces méthodes :

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
}

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

De cette façon, l'activité repasse par onCreate et appelle ensuite la méthode onRestoreInstanceState où vous pouvez à nouveau définir la valeur de votre EditText.

Si vous souhaitez stocker des objets plus complexes, vous pouvez utiliser la fonction

@Override
public Object onRetainNonConfigurationInstance() {
}

Ici vous pouvez stocker n'importe quel objet et dans onCreate vous avez juste à appeler getLastNonConfigurationInstance(); pour obtenir l'objet.

4 votes

OnRetainNonConfigurationInstance() est maintenant déprécié comme le dit la Doc : [developer.Android.com/reference/Android/app/](http://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance()) setRetainInstance(boolean retain) doit être utilisé à la place : developer.Android.com/reference/Android/app/

0 votes

@ForceMagic setRetainInstance est complètement différent : il s'agit de Fragments et il ne vous garantit pas que l'instance sera retenue.

4voto

SAAM Points 258

Il suffit d'ajouter Android:configChanges="orientation" avec votre élément d'activité dans AndroidManifest.xml

Exemple :

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

0 votes

Cela peut entraîner un affichage incorrect de la boîte de dialogue dans certaines circonstances.

2 votes

Android:configChanges="orientation|screenSize" Remarque : si votre application est destinée à Android 3.2 (niveau 13 de l'API) ou à une version ultérieure, vous devez également déclarer la configuration "screenSize", car elle change également lorsqu'un appareil passe de l'orientation portrait à l'orientation paysage.

1voto

Ioane Sharvadze Points 1223

Cette question a reçu une réponse il y a longtemps.

Pourtant, c'est non-hacky y simple solution que j'utilise pour moi-même.

Je l'ai fait. cette classe d'aide pour moi-même, afin que vous puissiez l'utiliser dans votre application également.

L'usage est :

PersistentDialogFragment.newInstance(
        getBaseContext(),
        RC_REQUEST_CODE,
        R.string.message_text,
        R.string.positive_btn_text,
        R.string.negative_btn_text)
        .show(getSupportFragmentManager(), PersistentDialogFragment.TAG);

Ou

 PersistentDialogFragment.newInstance(
        getBaseContext(),
        RC_EXPLAIN_LOCATION,
        "Dialog title", 
        "Dialog Message", 
        "Positive Button", 
        "Negative Button", 
        false)
    .show(getSupportFragmentManager(), PersistentDialogFragment.TAG);

public class ExampleActivity extends Activity implements PersistentDialogListener{

        @Override
        void onDialogPositiveClicked(int requestCode) {
                switch(requestCode) {
                  case RC_REQUEST_CODE:
                  break;
                }
        }

        @Override
        void onDialogNegativeClicked(int requestCode) {
                switch(requestCode) {
                  case RC_REQUEST_CODE:
                  break;
                }          
        }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X