5

I have been trying to get my head around this for a couple of hours now.

I have a main Fragment class, then from the onClick I have set up from an ImageView in that class , I am starting a Dialog Fragment with a simple "Yes" or "Cancel" option.

How would I make it so that when the user clicks "Ok", it will then send a Result code back to my main Fragment telling it to run some code(In my case, I am setting wallpaper).

This sound simple but can't seem to figure it out. Thanks in advance.

Onclick where I would like to somehow get the result back to:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    final View v = inflater.inflate(R.layout.image_detail_fragment,
            container, false);

    mImageView = (RecyclingImageView) v.findViewById(R.id.imageView);
    mImageView.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {

            MyDialogFragment dialog = new MyDialogFragment();
            dialog.show(getActivity().getFragmentManager(),
                    "MyDialogFragment");

        }

        public void onDialogOKPressed() {

    ((ImageDetailFragment) (DialogFragment.this.getParentFragment()))
                    .onDialogOKPressed();
            dismiss();

        }
    });

    return v;
}

Dialog class:

class MyDialogFragment extends DialogFragment {
    private Button ButtonOk;
    private Button ButtonCancel;

    public MyDialogFragment() {

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.prompt, container);
        ButtonOk = (Button) view.findViewById(R.id.button1);
        ButtonCancel = (Button) view.findViewById(R.id.button2);
        getDialog().setTitle("Set Wallpaper?");

        ButtonOk.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                                                ((MyDialogFragment)(DialogFragment.this.getActivity())).onDialogOKPressed();
                dismiss();


            }

        });

        ButtonCancel.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                MyDialogFragment.this.dismiss();

            }
        });

        return view;

    }
}
Bryan
  • 14,756
  • 10
  • 70
  • 125
Jack
  • 2,043
  • 7
  • 40
  • 69

4 Answers4

8

In your activity, add a method that responds to the OK button being pressed, such as public void onDialogOKPressed(). Then, in the onClickListener of your OK button in the DialogFragment, do this:

public void onClick(View v){
    ((MyActivity)(DialogFragment.this.getActivity())).onDialogOKPressed();
    dismiss();
}

or put the new method into your main fragment and do this:

public void onClick(View v){
    ((MyMainFragment)(DialogFragment.this.getParentFragment())).onDialogOKPressed();
    dismiss();
}
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • Then how would I go about getting the result back so that the main activity knows to execute my code or not? That was my question :) – Jack Oct 10 '13 at 13:41
  • This just calls your new method in your activity. So execute your code from this new method. It won't get called if the OK button isn't pressed. Get rid of the if/else block with the result code. Looks like you're planning to set a wallpaper, so in the new method, set your wallpaper. – Tenfour04 Oct 10 '13 at 14:00
  • Alternatively, you could put the new method into your fragment and replace `((MyActivity)getActivity())` with `((MyFragment)getParentFragment())`. – Tenfour04 Oct 10 '13 at 14:05
  • What would I be replacing "MyActivty" with? – Jack Oct 10 '13 at 14:23
  • Whatever the name of your activity is that's hosting the fragment. But actually it might be easier to use your main fragment class like I commented above, since that's probably where most of your wallpaper code is. So use `((MyFragment)getParentFragment())`, replacing MyFragment with whatever the name of your main fragment class is. – Tenfour04 Oct 10 '13 at 15:00
  • Could give me an example of what you're telling me to do using my code, I'm confused. Are you saying I should put "((MyDialogFragment)getParentFragment()).onDialogOKPressed();" in the on CLick of my DialogFragment, or in my other class? Sorry for not understanding – Jack Oct 10 '13 at 15:13
  • No not (MyDialogFragment). Use the name of your main fragment, the one that opens the dialog fragment. – Tenfour04 Oct 10 '13 at 15:17
  • I've updated my answer with what it looks like now. But I am getting errors "The method getParentFragment() is undefined for the type new View.OnClickListener(){}" and "The method onDialogOKPressed() is undefined for the type ImageDetailFragment" – Jack Oct 10 '13 at 15:20
  • Oops, see update. Since you're calling the dialog fragment's method from within the listener class, you have to specify that you want to call the outer method. – Tenfour04 Oct 10 '13 at 15:29
  • I've chosen to do the first option. I am getting an error "Cannot cast from Activity to MyDialogFragment" I've updated my answer so you can see what it looks like – Jack Oct 10 '13 at 15:35
  • You're trying to cast the activity to MyDialogFragment. If you use this option, you need to be casting to the name of whatever activity is hosting the main fragment. But if you do it this way, your activity will then have to ask your main fragment which wallpaper to set, so it will be more complicated. – Tenfour04 Oct 10 '13 at 15:48
  • Ok, I have created a "public void onDialogOKPressed()" in my main class, But am still getting errors. I've updated my answer. – Jack Oct 10 '13 at 16:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/38992/discussion-between-jack-and-tenfour04) – Jack Oct 10 '13 at 16:17
2

I know this is an old question, but the accepted answer seems dubious; especially the first method. Using this method would introduce tight coupling between MyDialogFragment and MyActivity, essentially defeating the purpose of using a Fragment. A Fragment should only know that it is attached to an Activity, not what kind of Activity it is.

While the second method is not as bad, considering your Activity already knows what kind of Fragment it will use, I still think there is a better method using an interface:

public class MyDialogFragment extends DialogFragment {

    public interface OnOkButtonClickListener {
        void onOkButtonClick();
    }

    private OnOkButtonClickListener mOnOkButtonClickListener;

    private Button mOkButton;
    private Button mCancelButton;

    public static MyDialogFragment newInstance() {
        return new MyDialogFragment();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        if(context instanceof OnOkButtonClickListener) {
            mOnOkButtonClickListener = (OnOkButtonClickListener) context;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.prompt, container, false);
        getDialog().setTitle("Set Wallpaper?");

        mOkButton = (Button) view.findViewById(R.id.button1);
        mCancelButton = (Button) view.findViewById(R.id.button2);

        mOkButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mOnOkButtonClickListener != null) {
                    mOnOkButtonClickListener.onOkButtonClick();
                }
            }
        };

        mCancelButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyDialogFragment.this.dismiss();
            }
        };
    }

}

Then you can implement the interface in any Activity:

public class MyActivity extends AppCompatActivity
        implements MyDialogFragment.OnOkButtonClickListener {


    @Override
    public void onOkButtonClick() {
        // TODO: handle dialog click
    }

    // ...

}

This is also the recommended method for communicating with a Fragment on the developer training site.

Bryan
  • 14,756
  • 10
  • 70
  • 125
0

You can try to use Otto (or EventBus) for sending events to MainActivity from dialog through "Events" Otto: http://square.github.io/otto/ EventBus: https://github.com/greenrobot/EventBus

Timofey Orischenko
  • 1,148
  • 1
  • 9
  • 12
0

Your dialog

class MyDialog(call: (Result) -> Unit) : DialogFragment() {

   companion object {
       const val TAG = "DIALOG_TAG"
   }
  
}

Your fragment

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   val dialog = MyDialog{result ->
        
   }
   dialog.show(requireActivity().supportFragmentManager, MyDialog.TAG)
}
Andrei Naumets
  • 171
  • 1
  • 8
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 19 '22 at 11:53