How to dismiss a DialogFragment without going back to last item in stack

五迷三道 提交于 2019-12-08 14:03:32

问题


In trying to clean up code in an existing project and remove warnings about calling showDialog() in an Activity, I have moved a bunch of related dialogs which show up in a sequence into a new DialogFragment class. It's working OK, however when I press the cancel button on a given dialog, it always takes me back to the previous dialog (which was saved to the back stack), whereas I want the cancel button to dismiss all of the Dialogs and go back to the View in the main activity.

Pressing the back button should continue to go back to the previous dialog on the back stack.

Here is my current code, I have simplified it to include only two dialogs, though there are several more dialogs in the chain between these two, which show up in my actual application before import() is called.

public class ImportDialog extends DialogFragment {
    private int mType = 0;

    public static final int DIALOG_IMPORT_HINT = 0;
    // ... several more
    public static final int DIALOG_IMPORT = 8;



    public interface ImportDialogListener {
        public void import();
        public void showImportDialog(int type);
        public void dismissAllDialogFragments();
    }


    /**
     * A set of dialogs which deal with importing a file
     * 
     * @param dialogType An integer which specifies which of the sub-dialogs to show
     */
    public static ImportDialog newInstance(int dialogType) {
        ImportDialog f = new ImportDialog();
        Bundle args = new Bundle();
        args.putInt("dialogType", dialogType);
        f.setArguments(args);
        return f;
    }


    @Override
    public AlertDialog onCreateDialog(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mType = getArguments().getInt("dialogType");
        Resources res = getResources();
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        setCancelable(true);

        switch (mType) {
            case DIALOG_IMPORT_HINT:
                // First dialog
                builder.setTitle("Title");
                builder.setMessage("Message");
                builder.setPositiveButton(res.getString(R.string.dialog_ok), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((ImportDialogListener) getActivity()).showImportDialog(DIALOG_IMPORT_SELECT);
                    }
                });
                builder.setNegativeButton(res.getString(R.string.dialog_cancel), mNegativeClickListener);
                return builder.create();

            // ... several more

            case DIALOG_IMPORT:
                // Second dialog
                builder.setTitle("Different title");
                builder.setMessage("Different message");
                builder.setPositiveButton(res.getString(R.string.import_message_add),
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ((ImportDialogListener) getActivity()).import();
                            }
                        });

                builder.setNegativeButton(res.getString(R.string.dialog_cancel), mNegativeClickListener);
                builder.setCancelable(true);
                return builder.create();

            default:
                return null;
        }
    }

    private DialogInterface.OnClickListener mNegativeClickListener = new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            ((ImportDialogListener) getActivity()).dismissAllDialogFragments(); 
        }
    };
}

Then in the main Activity I implement the ImportDialogListener interface as follows:

public void showImportDialog(int type) {
    // DialogFragment.show() will take care of adding the fragment
    // in a transaction.  We also want to remove any currently showing
    // dialog, so make our own transaction and take care of that here.
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
    if (prev != null) {
        ft.remove(prev);
    }
    // save transaction to the back stack (input argument is optional name) so it can be reversed
    ft.addToBackStack(null);
    DialogFragment newFragment = ImportDialog.newInstance(type);
    newFragment.show(ft, "dialog");
}

public void import() {
    // Do stuff
}

// Dismiss whatever dialog is showing... THIS IS THE PART THAT DOESN'T WORK
public void dismissAllDialogFragments() {
    getSupportFragmentManager().popBackStack("dialog", FragmentManager.POP_BACK_STACK_INCLUSIVE);
    Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
    if (prev != null) {
        DialogFragment df = (DialogFragment) prev;
        df.dismiss();
    }
}

How can I get it to work, and am I doing something fundamentally wrong here?


回答1:


While adding a transaction to back stack, supply the name for the back stack state. e.g. dialog

Change

ft.addToBackStack(null);

to

ft.addToBackStack("dialog");

To remove entries from back stack matching a back stack state name, use FragmentManager.popBackStack. This removes all back stack states with name dialog from top until bottom of stack is reached or a back stack state entry with different name is reached. No need to explicitly call dismiss on dialog.

public void dismissAllDialogFragments() {
    getSupportFragmentManager().popBackStack("dialog", FragmentManager.POP_BACK_STACK_INCLUSIVE);
}


来源:https://stackoverflow.com/questions/25598740/how-to-dismiss-a-dialogfragment-without-going-back-to-last-item-in-stack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!