web-dev-qa-db-fra.com

Android DialogFragment disparaît après le changement d'orientation

J'ai une classe de prise en charge FragmentActivity v4 qui implémente deux fragments côte à côte (un peu comme Gmail) et un bouton qui peut afficher un DialogFragment. 

Tout cela fonctionne très bien, sauf si j'ai un changement d'orientation. Lorsque j'ai une orientation, les états des fragments ne sont pas sauvegardés.

Et le problème principal est que si j'ai un FragmentDialog ouvert, il disparaît tout simplement.  

J'ai mis setRetainInstance(true); dans tous les fragments mais cela n'a pas aidé.

Dans mon manifeste, j'ai inclus Android:configChanges="orientation" mais cela n'aide toujours pas.

Voici mes exemples de code, merci de votre aide.

public class AddMasterDialog extends DialogFragment {

    private int mTitle;
    private int mPrompt;
    private OnClickListener onSaveListener;
    private OnClickListener onCancelListener;

    public AddMasterDialog newInstance(int title, int Prompt) {
        AddMasterDialog simpleDialog = new AddMasterDialog(title, Prompt);
        return simpleDialog;
    }

    public AddMasterDialog() {
        // Empty constructor required for DialogFragment
    }
    public AddMasterDialog(int title, int Prompt) {
        // Empty constructor required for DialogFragment
        mTitle = title;
        mPrompt = Prompt;
    }
    public void setSaveButton(OnClickListener save){
        onSaveListener = save;
    }
    public void setCancelButton(OnClickListener cancel){
        onCancelListener = cancel;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

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

        //if(savedInstanceState == null){
            View view = inflater.inflate(R.layout.add_new_simple, container);
            getDialog().setTitle(mTitle);
            ((TextView) view.findViewById(R.id.add_simple_new_value_Prompt)).setText(mPrompt);

            Button saveButton = (Button) view.findViewById(R.id.add_simple_save_button);
            saveButton.setOnClickListener(onSaveListener);

            //Cancel Button
            Button cancelButton = (Button) view.findViewById(R.id.add_simple_cancel_button);
            cancelButton.setOnClickListener(onCancelListener);
            return view;
        //}
    }
}

et dans mon activité principale:

private void initiateAddMasterPopupWindow() {
        try {
            addMasterDialog = new AddMasterDialog(R.string.add_new_master_dialog_title, R.string.add_master_new_value_Prompt);
            addMasterDialog.setSaveButton(saveNewMasterClickListener);
            addMasterDialog.setCancelButton(cancelNewMasterClickListener);
            FragmentManager fm = getSupportFragmentManager();
            addMasterDialog.show(fm, ADD_NEW_MASTER);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
35
AlexIIP

D'accord, le problème semble être lié à la bibliothèque de compatibilité DialogFragment

Le problème a été décrit dans this post.

"Un message DISMISS obsolète pour le fragment est conservé dans la file de messages. Il a été mis en file d'attente par DialogFragment.onDestroyView() lors de la fermeture de l'ancienne boîte de dialogue et est réactivé après la création de la nouvelle boîte de dialogue.

Une solution rapide (et peut-être sale) consiste à remplacer onDestroyView() et à effacer l'auditeur de renvoi avant d'appeler super.onDestroyView() ".

L'ajout du code suivant à mon DialogFragment a résolu le problème:

 @Override
 public void onDestroyView() {
     if (getDialog() != null && getRetainInstance()) {
         getDialog().setDismissMessage(null);
     }
     super.onDestroyView();
 }
72
AlexIIP

Dans l’intérêt de la pauvre âme (moi) qui a le même problème pour différentes raisons, je vais publier ceci. Le fragment de dialogue doit être préservé automatiquement aussi longtemps que vous effectuez les opérations suivantes:

  1. Si vous appelez une Activity onSaveInstanceState(), assurez-vous d'appeler la super fonction !!!! . Dans mon cas, c'était la clé. Assurez-vous également de faire la même chose dans le fragment.
  2. Si vous utilisez setRetainInstance, vous devrez stocker manuellement les valeurs et les réappliquer. Sinon, vous devriez pouvoir ne pas vous en préoccuper, dans la plupart des cas. Si vous faites quelque chose d'un peu plus compliqué, vous devrez peut-être setRetainInstance(true), mais sinon ignorez-le. Dans mon cas, je devais l'utiliser pour stocker une graine aléatoire pour l'un de mes cours, mais sinon, ça allait.
  3. Certaines personnes se sont plaintes d'un bogue dans la bibliothèque de support, où un message de renvoi est envoyé alors qu'il ne devrait pas l'être. La dernière bibliothèque de support semble avoir résolu ce problème, vous ne devriez donc pas avoir à vous en préoccuper.

Vous ne devriez pas avoir besoin de faire quelque chose d'extraordinaire comme de stocker manuellement le fragment, cela devrait être fait automatiquement si vous suivez ces étapes. Globalement, cela semble faire l'affaire pour tous ceux qui possèdent une bibliothèque de support plus moderne.

13
PearsonArtPhoto

Dans mon cas, j'avais un DialogFragment montrant un autre DialogFragment en utilisant

listDialogFragment.show(getChildFragmentManager(), "TAG");

En le changeant en

listDialogFragment.show(getActivity().getSupportFragmentManager(), "TAG");

corrigé le problème

2
Maragues

En plus de définir setRetainInstance(true);, placez simplement le code suivant dans votre DialogFragment. C'est une solution testée.

private boolean isDismissible = false;

@Override
public void dismiss() {

    try {

        isDismissible = true;
        super.dismiss();

        Log.d(getClass().getSimpleName(), "Dialog dismissed!");

    } catch (IllegalStateException ilse) {
    }
}

@Override
public void onDismiss(DialogInterface dialog) {

    // So that dialog should not dismiss on orientation change
    if (isDismissible) {

        // So that dialog can be dismissed
        super.onDismiss(dialog);
    }
}
1
Azmat Ali Khan