Android DialogFragment исчезает после изменения ориентации

У меня есть класс поддержки FragmentActivity v4, который реализует два расположенных рядом (вроде gmail) фрагмента и кнопку, которая может вызывать DialogFragment.

Все это отлично работает, если у меня нет смены ориентации. Когда у меня меняется ориентация, состояния фрагментов не сохраняются.

И основная проблема заключается в том, что если у меня открыт FragmentDialog, он просто исчезает.

Я поставил setRetainInstance(true); во всех фрагментах, но это не помогло.

В моем манифесте я включил android:configChanges="orientation", но это все равно не помогает.

Вот мои примеры кода, спасибо за помощь.

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;
        //}
    }
}

и в моей основной деятельности:

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

person AlexIIP    schedule 14.09.2012    source источник


Ответы (4)


Итак, проблема, похоже, связана с библиотекой совместимости DialogFragment.

Проблема описана в этом сообщении.

«Устаревшее сообщение DISMISS для фрагмента сохраняется в очереди сообщений. Оно поставлено в очередь DialogFragment.onDestroyView() при закрытии старого диалога и повторно активируется после создания нового диалога.

Быстрый (и, возможно, грязный) обходной путь — переопределить onDestroyView() и очистить прослушиватель отклонения перед вызовом super.onDestroyView()».

Добавление следующего кода в мой DialogFragment решило проблему:

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

В интересах бедной души (меня), у которой такая же проблема по разным причинам, я собираюсь опубликовать это. Фрагмент диалога должен сохраняться автоматически, пока вы делаете следующее:

  1. Если вы вызываете Activity onSaveInstanceState(), убедитесь, что вы вызываете суперфункцию!!!!. В моем случае это был ключ. Также убедитесь, что вы делаете то же самое во фрагменте.
  2. Если вы используете setRetainInstance, вам нужно будет вручную сохранить значения и повторно применить их. В противном случае вы должны быть в состоянии не беспокоиться об этом, в большинстве случаев. Если вы делаете что-то более сложное, вам может понадобиться setRetainInstance(true), но в противном случае проигнорируйте его. В моем случае мне нужно было использовать его для хранения случайного начального числа для одного из моих классов, но в остальном я был в порядке.
  3. Некоторые люди жаловались на ошибку в библиотеке поддержки, из-за которой сообщение об отклонении отправляется, когда этого не должно быть. Последняя библиотека поддержки, кажется, исправила это, так что вам не о чем беспокоиться.

Вам не нужно делать ничего особенного, например, вручную сохранять фрагмент, это должно быть сделано автоматически, если вы выполните следующие шаги. В целом, это, похоже, поможет любому, у кого есть более современная библиотека поддержки.

person PearsonArtPhoto    schedule 31.12.2013

В моем случае у меня был DialogFragment, показывающий другой DialogFragment, использующий

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

Изменение его на

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

исправлена ​​проблема

person Maragues    schedule 25.11.2014
comment
NB ваше изменение точно такое же, как вызов listDialogFragment.show(getFragmentManager(), "TAG"); - person William; 11.12.2014

В дополнение к настройке setRetainInstance(true); просто поместите следующий код в файл DialogFragment. Это проверенное решение.

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);
    }
}
person Azmat Ali Khan    schedule 25.04.2014
comment
Он создает несколько диалогов по изменению ориентации. - person Hrushikesh Salkade; 02.06.2016