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