it-swarm.com.ru

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

У меня есть класс v4 поддержки FragmentActivity, который реализует два соседних (типа 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();
        }
    }
35
AlexIIP

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

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

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

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

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

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

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

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

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

13
PearsonArtPhoto

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

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

Меняя его на

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

исправил проблему

2
Maragues

В дополнение к настройке 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);
    }
}
1
Azmat Ali Khan