Search code examples
androidinterfaceandroid-listfragmentdialogfragment

DialogFragment Interface that Can Be Implemented in Activities and Fragments


I have a ListFragment with a context menu for my ListItems. One of the menu options is for deleting the item, and I want to show a confirmation dialog to the user to prevent accidental deletes.

public class MyListFragment extends ListFragment implements ConfirmDeletePopupFragment.DialogListener {

    (...)

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.action_delete:
                ConfirmDeletePopupFragment fragment = new ConfirmDeletePopupFragment();
                fragment.show(getSupportFragmentManager(), "tag");
                return true;
            case R.id.action_cancel:
                return true;
            default:
                return super.onContextItemSelected(item);
        }
    }

}

For a similar situation, I have created a generic confirmation dialog as a DialogFragment as shown below. This I can use to let the user confirm any critical actions. For use in an Activity it has an Interface with a method onDeleteConfirm that handles the actual deletion in the Activity which created the dialog.

public class ConfirmDeletePopupFragment extends DialogFragment {

    (...)

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mDialogListener = (DialogListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(getTargetFragment().toString() + " must implement ConfirmDeletePopupFragment.DialogListener");
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final android.app.AlertDialog.Builder dialogBuilder = new android.app.AlertDialog.Builder(getActivity());
        final LayoutInflater inflater = getActivity().getLayoutInflater();
        final View dialogView = inflater.inflate(R.layout.popup_confirm_delete, null);
        dialogBuilder.setView(dialogView);

        dialogBuilder.setTitle("Delete?");

        dialogBuilder.setNegativeButton(getString(R.string.activities_confirm_deletion_cancel_button), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            }
        });
        dialogBuilder.setPositiveButton(getString(R.string.activities_confirm_deletion_delete_button), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                ((DialogListener) getActivity()).onDeleteConfirm();
            }
        });

        deleteDialog = dialogBuilder.create();
        deleteDialog.show();
        return deleteDialog;
    }

    public interface DialogListener {
        void onDeleteConfirm();
    }
}

Obviously, this interface only works when the dialog is created in an Activity (((DialogListener) getActivity()).onDeleteConfirm();). For the problem mentioned above, I need to create the dialog from within a Listfragment, and just implementing the dialog interface in the ListFragment does not work ("Activity must implement ConfirmDeletePopupFragment.DialogListener")

What would be the best way to adapt my DialogFragment so it would accommodate both cases (created in Activity or Fragment)?


Solution

  • When showing dialog (in fragment) :

    <dialog>.setTargetFragment(<your fragment>);
    <dialog>.show();
    

    In activity skip setTargetFragment.

    In DialogFragment code:

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (getTargetFragment() != null) {
            myInterface = (YourCastInterface) getTargetFragment();
        } else {
            myInterface = (YourCastInterface) activity;
        }
    }