Implement DialogFragment interface in OnClickListener

15,422

Solution 1

Something like this?

public class CustomNumberPicker extends DialogFragment {
    private NoticeDialogListener ndl;

    public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
    }

    //add a custom constructor so that you have an initialised NoticeDialogListener
    public CustomNumberPicker(NoticeDialogListener ndl){
        super();
            this.ndl=ndl;
    }

    //make sure you maintain an empty constructor
    public CustomNumberPicker( ){
        super();
    }

    // Use this instance of the interface to deliver action events
    NoticeDialogListener mListener;

    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        //remove the check that verfis if your activity has the DialogListener Attached because you want to attach it into your list view onClick()
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage("Sets")
            .setPositiveButton("set", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        ndl.onDialogPositiveClick(dialog);
                    }
                })
                .setNegativeButton("cancle", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                       ndl.onDialogNegativeClick(dialog);
                    }
                });
        // Create the AlertDialog object and return it
        return builder.create();
    }
}

and then your listView onClick becomes:

tvSets.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // This is where the Dialog should be called and
                    // the user input from the Dialog should be returned
                    // 
                    // 


                    DialogFragment numberpicker = new CustomNumberPicker(new NoticeDialogListener() {

            @Override
            public void onDialogPositiveClick(DialogFragment dialog) {
                //What you want to do incase of positive click

            }

            @Override
            public void onDialogNegativeClick(DialogFragment dialog) {
               //What you want to do incase of negative click

            }
        };);
                    numberpicker.show(MainActivity.this.getSupportFragmentManager(), "NoticeDialogFragment");
                }

                // Here I would like to implement the interface of CustomNumberPicker
                // in order to get the user input entered in the Dialog
            });

Do read the comments I have added.And it can even be further optimized because you really dont need an entire dialog instance to get the values you need.

EDIT a possible optimization could be:

Changing the Listener interface to :

public interface NoticeDialogListener {
        public void onDialogPositiveClick(String output);
        public void onDialogNegativeClick(String output);
       //or whatever form of output that you want
    }

Then modify the implemented methods accordingly.

Solution 2

You should have your activity, implement your interface (NoticeDialogListener).

public class MainActivity extends ActionBarActivity implements
    NoticeDialogListener{

    @Override
    public void onDialogPositiveClick(DialogFragment dialog){
        //Do something
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog){
        //Do some other things
    }

    [...]
}

Then in your button click listeners of the dialog, you use the mListener and call the methods, which is now implemented in the activity and the code will be executed there.

builder.setMessage("Sets")
            .setPositiveButton("set", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        if(mListener != null)
                            mListener.onDialogPositiveClick(CustomNumberPicker.this);
                    }
            });

Also note that you should set the mListener to null in the onDetach() method of your DialogFragment.

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}
Share:
15,422
tymm
Author by

tymm

Updated on June 05, 2022

Comments

  • tymm
    tymm about 2 years

    I need to build a DialogFragment which returns user input from the dialog to an activity. The dialog needs to be called in an OnClickListener which gets called when an element in a listview gets clicked.
    The return value of the DialogFragment (the input of the user) should be directly available in the OnClickListener in the activity.

    I tried to implement this by sticking to the official docs: http://developer.android.com/guide/topics/ui/dialogs.html#PassingEvents

    I need something like the following which doesn't work since I don't know how to make the anonymous OnClickListener implement the interface of the CustomNumberPicker class.
    As far as I know implementing the interface is necessary in order to get data from the DialogFragment back to the Activity.

    Main Activity:

    public class MainAcitivity extends ActionBarActivity {
        [...]
    
        // ArrayAdapter of the Listview
        private class ListViewArrayAdapter extends ArrayAdapter<Exercise> {
            public ListViewArrayAdapter(Context context, ArrayList<Exercise> exercises) {
                super(context, 0, exercises);
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                [...]
    
                if (convertView == null) {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_workoutdetail, parent, false);
                }
    
                TextView tvSets = (TextView) convertView.findViewById(R.id.tvWorkoutExerciseSets);
                tvSets.setText(sets.toString());
    
                // OnClickListener for every element in the ListView
                tvSets.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // This is where the Dialog should be called and
                        // the user input from the Dialog should be returned
                        DialogFragment numberpicker = new CustomNumberPicker();
                        numberpicker.show(MainActivity.this.getSupportFragmentManager(), "NoticeDialogFragment");
                    }
    
                    // Here I would like to implement the interface of CustomNumberPicker
                    // in order to get the user input entered in the Dialog
                });
    
                return convertView;
            }
        }
    }
    

    CustomNumberPicker (basically the same as in the docs):

    public class CustomNumberPicker extends DialogFragment {
    
        public interface NoticeDialogListener {
            public void onDialogPositiveClick(DialogFragment dialog);
            public void onDialogNegativeClick(DialogFragment dialog);
        }
    
        // Use this instance of the interface to deliver action events
        NoticeDialogListener mListener;
    
        // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            // Verify that the host activity implements the callback interface
            try {
                // Instantiate the NoticeDialogListener so we can send events to the host
                mListener = (NoticeDialogListener) activity;
            } catch (ClassCastException e) {
                // The activity doesn't implement the interface, throw exception
                throw new ClassCastException(activity.toString()
                    + " must implement NoticeDialogListener");
            }
        }
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Use the Builder class for convenient dialog construction
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setMessage("Sets")
                .setPositiveButton("set", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // Return stuff here to the activity?
                        }
                    })
                    .setNegativeButton("cancle", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // User cancelled the dialog
                        }
                    });
            // Create the AlertDialog object and return it
            return builder.create();
        }
    }