10

I'm using RecyclerView to list some text and now I want to make it so that when the user clicks on text a custom Alert Dialog box pops up.

I have tried this so far but get a NullPointerException; what could be wrong here?

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

List<AdapterData> mItems;

public CBAdapter() {
    super();
    mItems = new ArrayList<>();
    AdapterData data = new AdapterData();
    data.setTextOne("Many Bows");
    mItems.add(data);

    data = new AdapterData();
    data.setTextOne("Pardon");
    mItems.add(data);

    data = new AdapterData();
    data.setTextOne("Fall To Knees & Beg");
    mItems.add(data);

    data = new AdapterData();
    data.setTextOne("Backflips");
    mItems.add(data);



}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.test3, viewGroup, false);
    return new ViewHolder(v);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
    AdapterData data = mItems.get(i);
    viewHolder.textOne.setText(data.getTextOne());

}


@Override
public int getItemCount() {

    return mItems.size();
}

class ViewHolder extends RecyclerView.ViewHolder{

    public TextView textOne;
    private Context context;





    public ViewHolder(View itemView) {
        super(itemView);
        textOne = (TextView)itemView.findViewById(R.id.textView1);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                final Dialog dialog = new Dialog(context);
                dialog.setContentView(R.layout.custom_dialog);
                dialog.setTitle("Title");

                TextView text = (TextView) dialog.findViewById(R.id.text);
                text.setText("hello world");

                ImageView image = (ImageView) dialog.findViewById(R.id.image);
                image.setImageResource(R.drawable.ic_launcher);

                Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);

                dialogButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        dialog.dismiss();
                    }
                });

                dialog.show();
            }
        });


    }
}
}
Jacques Krause
  • 5,523
  • 9
  • 27
  • 43

6 Answers6

6

Nevermind I forgot the initialization my context

context = itemView.getContext();

Jacques Krause
  • 5,523
  • 9
  • 27
  • 43
3

This is not the answer for your query but the better way to handle this scenario.

Use callback methods.

In your Activity:

This will implement the interface that we have in our Adapter. In this example, it will be called when the user clicks on an item in the RecyclerView.

  public class MyActivity extends Activity implements AdapterCallback {

    private MyAdapter mMyAdapter;

    @Override
    public void onMethodCallback() {
       // Show your alert
    }

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.mMyAdapter = new MyAdapter(this);
    }
}

In your Adapter:

In the Activity, we initiated our Adapter and passed this as an argument to the constructor. This will initiate our interface for our callback method. You can see that we use our callback method for user clicks.

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

    private AdapterCallback mAdapterCallback;

    public MyAdapter(Context context) {
        try {
            this.mAdapterCallback = ((AdapterCallback) context);
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement AdapterCallback.");
        }
    }

    @Override
    public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) {
        // simple example, call interface here
        // not complete
        viewHolder.itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mAdapterCallback.onMethodCallback();
                } catch (ClassCastException exception) {
                   // do something
                }
            }
        });
    }

    public static interface AdapterCallback {
        void onMethodCallback();
    }
}

Courtesy : Call Activity method from adapter

Community
  • 1
  • 1
Anoop M Maddasseri
  • 10,213
  • 3
  • 52
  • 73
2
final Dialog dialog = new Dialog(your_activity_context);
Nikunj
  • 3,937
  • 19
  • 33
0

You are using context which is null so pass the context in ViewHolder constructor and in CBAdapter constructor also like as below:

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

List<AdapterData> mItems;
Context context;

public CBAdapter(Context context) {
    super();
    this.context = context;
    .....
  }

And in ViewHolder class

class ViewHolder extends RecyclerView.ViewHolder{

    public TextView textOne;
    private Context mcontext;


    public ViewHolder(View itemView, Context mcontext) {
        super(itemView);
        this.mcontext = mcontext;
        ....
   }
Pankaj
  • 7,908
  • 6
  • 42
  • 65
0

Not directly related to the question, although I beg you: DO NOT set onClickListener-s inside adapter!

This is how it should be done:

private class ItemDataHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener{

    private final String TAG = ItemDataHolder.class.getSimpleName();

    /**
     * Define view's elements
     */

    /**
     *  Define object instance
     */
    private Item mData;

    // Constructor
    public MessageDataHolder(View itemView) {
        super(itemView);
        /**
         * Init elements
         */
        itemView.setOnLongClickListener(this);
    }

    /**
     * Method to handle long click on the item
     * @param v View to handle click on
     * @return
     */
    @Override
    public boolean onLongClick(View v) {
        Log.v(TAG, "Long click fired!");
        return false;
    }

    /**
     * Function to update view's elements
     * @param message Good data to be updated to
     */
    public void bindData(Item message) {
        mData = message;
        /**
        * Set values of views here
        **/
    }
}

Hope my answers helps someone to write a better code :)

jujka
  • 1,190
  • 13
  • 18
  • 1
    If you're so specific about not setting onClickListeners inside the adapter, would you mind telling us why this is, so we can all learn from your knowledge? Also, how would we have two buttons that do different things? – Timmiej93 Apr 12 '16 at 22:26
-2

Write this code:

 final Dialog dialog = new Dialog(CBAdapter.this);

instead of

final Dialog dialog = new Dialog(context);

(or)

context = CBAdapter.this; // Initialize context

Hope this helps.

Happy Coding :)

Venkatesh Selvam
  • 1,382
  • 2
  • 15
  • 28
  • this does not provide an answer to the question, and Adapter class can't have Context available except the activity – Umar Ata Jan 05 '17 at 06:38