I have a FragmentActivity support v4 class which implements two side by side (kind of like gmail) fragments and a button which can bring up a DialogFragment.
This all works great unless I have an orientation change. When I have an orientation change the states of the Fragments are not saved.
And the main problem is if I have a the FragmentDialog open, it simply disappears.
I have set setRetainInstance(true);
in all fragments but it did not help.
In my manifest I included android:configChanges="orientation"
but is still does not help.
Here are my code samples, thank you for the help.
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;
//}
}
}
and in my Main activity:
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();
}
}
Okay, so the issue seems to be with the DialogFragment
compatibility library.
The issue was described in this post.
"An obsolete DISMISS message for the fragment is retained in the message queue. It's been queued by DialogFragment.onDestroyView()
when dismissing the old dialog and gets reactivated after creating the new dialog.
A quick (and possibly dirty) workaround is to override onDestroyView()
and clear the dismiss listener before calling super.onDestroyView()
"
Adding the following code to my DialogFragment solved the issue:
@Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance()) {
getDialog().setDismissMessage(null);
}
super.onDestroyView();
}
In the interest of the poor soul (Me) who has the same issue for different reasons, I'm going to post this. The dialog fragment should be preserved automatically as long as you do the following:
- If you call an
Activity onSaveInstanceState()
, make sure you call the super function!!!!. In my case, that was the key. Also make sure you do the same thing in the Fragment. - If you use
setRetainInstance
, you will need to manually store off the values and re-apply them. Otherwise, you should be able to not worry about it, in most cases. If you're doing something a bit more complicated, you might need tosetRetainInstance(true)
, but otherwise ignore it. In my case, I needed to use it to store a random seed for one of my classes, but otherwise I was okay. - Some people have complained about a bug in the support library, where a dismiss message is sent when it shouldn't be. The latest support library seems to have fixed that, so you shouldn't need to worry about that.
You shouldn't need to do anything fancy like manually store off the fragment, it should be done automatically if you follow these steps. Overall, this seems to do the trick for anyone with a more modern support library.
In my case I had a DialogFragment showing another DialogFragment using
listDialogFragment.show(getChildFragmentManager(), "TAG");
Changing it to
listDialogFragment.show(getActivity().getSupportFragmentManager(), "TAG");
fixed the issue
In addition to setting setRetainInstance(true);
just place the following code in your DialogFragment
. It is a tested solution.
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);
}
}
来源:https://stackoverflow.com/questions/12433397/android-dialogfragment-disappears-after-orientation-change