Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

Calling a DialogFragment from a RecyclerView

Hello.

I wanted to know if there was a way I could call a DialogFragment from a RecyclerView. Let's say I want to press something in my ViewHolder that would open up a DialogFragment, how would I do that?

Thank you.

2 Answers

Kourosh Raeen
Kourosh Raeen
23,733 Points

Hi Diego - You can create a custom click listener interface in your RecyclerView adapter and then have your activity/fragment containing the RecyclerView implement this interface. The interface will have one method that you implement in the activity/fragment and in the body of that method you create and show your custom DialogFragment. You then call this method in your ViewHolder class in the adapter. Take a look at the code in this link for more detail:

http://stackoverflow.com/questions/38324856/how-to-call-dialogfragment-from-recyclerview-viewholder-with-interface-implemen

Okay. But what if I want to press a button in my DialogFragment, how would I access the button I want to press if the fragment is it's own class?

Kourosh Raeen
Kourosh Raeen
23,733 Points

In the onCreateView method of the class that's extending DialogFragment you can get a reference to the button using findViewById and then set a click listener on it.

I meant from my ViewHolder; I want something to be pressed in my ViewHolder that opens up the DialogFragment. I was curious because I'm still having trouble accessing my DialogFragment in my ViewHolder.

Kourosh Raeen
Kourosh Raeen
23,733 Points

If you have a reference, in your ViewHolder, to the item that you want to press that opens the DialogFragment then you should be able to call setOnClickListener on it and then in the overridden onClick method you can either create the DialogFragment or if you're using a custom click listener interface, as in my post above, you can call the interface's method. If you still have trouble with this please share the code so I can take a look at it.

Here is my code for my DialogFragment I want to access:

public class PromptDeleteDialogFragment extends DialogFragment {
    private TextView mYesTextView;
    private TextView mNoTextView;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Context context = getActivity();
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_prompt, null);

        mYesTextView = (TextView) view.findViewById(R.id.yesTextView);
        mNoTextView = (TextView) view.findViewById(R.id.noTextView);

        AlertDialog dialog = builder.create();
        dialog.show();
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        return dialog;
    }
}

Code for ViewHolder in RecyclerView (I want the DialogFragment to open when mDeleteItemImage is pressed)

public class ViewHolder extends RecyclerView.ViewHolder {

        public CheckBox mCheckBox;
        public ImageView mDeleteItemImage;

        public ViewHolder(View itemView) {
            super(itemView);

            mCheckBox = (CheckBox) itemView.findViewById(R.id.checkBox);
            mDeleteItemImage = (ImageView) itemView.findViewById(R.id.deleteImage);

            mDeleteItemImage.setOnClickListener(listener);
        }

        public void bindHolder(ListItem item) {
            mCheckBox.setText(item.getAssignment());
        }

        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mListener.onItemClicked(v);
                removeAt(getAdapterPosition());
            }
        };
    }
Kourosh Raeen
Kourosh Raeen
23,733 Points

Where are mListener and onItemClicked() defined? Can you post the code for those?

Sure thing

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

    public interface OnItemClickListener {
        void onItemClicked(View v);
    }

    private ArrayList<ListItem> mList;
    private Context mContext;
    private OnItemClickListener mListener;

    public ListAdapter(OnItemClickListener listener, Context context, ArrayList<ListItem> items) {
        mListener = listener;
        mContext = context;
        mList = items;
    }
Kourosh Raeen
Kourosh Raeen
23,733 Points

Hi Diego - The code to create an instance of your DialogFragment and to show it needs to go in onItemClicked() in your MainActivity. I also suggest simplifying the related code in your ViewHolder. Remove the lines:

View.OnClickListener listener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
            mListener.onItemClicked(v);
            removeAt(getAdapterPosition());
    }
};

and change the line:

mDeleteItemImage.setOnClickListener(listener);

to:

mDeleteItemImage.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
           mListener.onItemClicked(v);
           removeAt(getAdapterPosition());         
    }
});

Alright, it's somewhat working; I'm getting an error when I press my button.

12-13 10:12:00.291 25576-25576/com.diego.quicklist E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: com.diego.quicklist, PID: 25576
                                                                     android.util.AndroidRuntimeException: requestFeature() must be called before adding content
                                                                         at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:325)
                                                                         at com.android.internal.app.AlertController.installContent(AlertController.java:231)
                                                                         at android.app.AlertDialog.onCreate(AlertDialog.java:356)
                                                                         at android.app.Dialog.dispatchOnCreate(Dialog.java:406)
                                                                         at android.app.Dialog.show(Dialog.java:279)
                                                                         at android.app.DialogFragment.onStart(DialogFragment.java:496)
                                                                         at android.app.Fragment.performStart(Fragment.java:2086)
                                                                         at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:922)
                                                                         at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
                                                                         at android.app.BackStackRecord.run(BackStackRecord.java:833)
                                                                         at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
                                                                         at android.app.FragmentManagerImpl$1.run(FragmentManager.java:447)
                                                                         at android.os.Handler.handleCallback(Handler.java:739)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                         at android.os.Looper.loop(Looper.java:135)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5351)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:372)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)

I believe it has something to do with the creation of my DialogFragment.

private TextView mYesTextView;
    private TextView mNoTextView;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Context context = getActivity();
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_fragment_prompt, null);
        AlertDialog dialog = builder.create();
        builder.setView(view);
        dialog.setContentView(R.layout.dialog_fragment_prompt);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        mYesTextView = (TextView) view.findViewById(R.id.yesTextView);
        mNoTextView = (TextView) view.findViewById(R.id.noTextView);

        return dialog;
    }
Kourosh Raeen
Kourosh Raeen
23,733 Points

The error might have to to with when you're calling create() on builder. See if moving this line:

AlertDialog dialog = builder.create();

to right before the return statement would get rid of the error.

I got it working! But what if I want to call dialog.setContentView()? How would I do that?

Kourosh Raeen
Kourosh Raeen
23,733 Points

Why do you need to call setContentView()? Haven't you already inflated the layout? By the way, I'm not sure if you've seen this tutorial so I'll post the link here. You may find some useful tips here: https://guides.codepath.com/android/Using-DialogFragment

Kourosh Raeen
Kourosh Raeen
23,733 Points

Can you post the body of the onItemClicked() method? Is that defined in an activity/fragment? I assume that's where you're creating an instance of PromptDeleteDialogFragment, is that correct?

This is everything I have for my onItemClicked() body (MainActivity):

@Override
    public void onItemClicked(View v) {

    }

The thing is that the button I want to press is in the ViewHolder for my RecyclerView, should I implement the listener there?