简体   繁体   中英

How can I make click event on CardView Item from RecyclerView

I referenced Simple Android RecyclerView example for make click events on items from Recyclerview. And then I apply this way to CardView from Recyclerview but I failed.

OnClick event on ViewHolder doesn't work. It looks like codes are almost same. I don't know what is the problem.

I just copied codes from the Simple Android RecyclerView example

And then changed ArrayList to ArrayList Also, I replace xml which contains textview code with cardview.

I succeeded the event when I put onClickListener on onBindViewHolder. But I heard it makes app heavier. So I want to avoid this way.

MainActivity.java

public class MainActivity extends AppCompatActivity implements MyAdapter.ItemClickListener{

    RecyclerView mRecyclerView;
    MyAdapter mAdapter;
    RecyclerView.LayoutManager mLayoutManager;
    ArrayList<MyData> myDataset;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        myDataset = new ArrayList<>();
        myDataset.add(new MyData("#InsideOut", R.drawable.a));
        myDataset.add(new MyData("#Mini", R.drawable.b));
        myDataset.add(new MyData("#ToyStroy", R.drawable.c));

        mAdapter = new MyAdapter(this, myDataset);
        mAdapter.setClickListener(this);
        mRecyclerView.setAdapter(mAdapter);
    }
    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(this, "You clicked " + mAdapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
    }
}

MyAdapter.java

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private ArrayList<MyData> mDataset;
    private LayoutInflater mInflater;

    private ItemClickListener mClickListener;


    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        // each data item is just a string in this case
        public ImageView mImageView;
        public TextView mTextView;
        public CardView cv;

        public ViewHolder(View view) {
            super(view);
            mImageView = (ImageView)view.findViewById(R.id.image);
            mTextView = (TextView)view.findViewById(R.id.textview);
            cv = (CardView)view.findViewById(R.id.cardview);
            view.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
            Log.d("이거이거", ""+getAdapterPosition());
        }
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(Context context, ArrayList<MyData> myDataset) {
        this.mDataset = myDataset;
        this.mInflater = LayoutInflater.from(context);
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = mInflater.inflate(R.layout.item_cardview, parent, false);
        return new ViewHolder(v);
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        Log.d("position", position+"");

        holder.mTextView.setText(mDataset.get(position).text);
        holder.mImageView.setImageResource(mDataset.get(position).img);

    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }
    MyData getItem(int id) {
        return mDataset.get(id);
    }

    void setClickListener(ItemClickListener itemClickListener) {
        this.mClickListener = itemClickListener;
    }
    public interface ItemClickListener {
        void onItemClick(View view, int position);
    }
}

class MyData{
    public String text;
    public int img;
    public MyData(String text, int img){
        this.text = text;
        this.img = img;
    }
}

There is also a way to do this

 public ViewHolder(final View view) {
        super(view);
        mImageView = (ImageView)view.findViewById(R.id.image);
        mTextView = (TextView)view.findViewById(R.id.textview);
        cv = (CardView)view.findViewById(R.id.cardview);

        cv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mClickListener != null) mClickListener.onItemClick( view,getAdapterPosition());
            }
        });
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
    // each data item is just a string in this case
    public ImageView mImageView;
    public TextView mTextView;
    public CardView cv;

    public ViewHolder(View view) {
        super(view);
        mImageView = (ImageView)view.findViewById(R.id.image);
        mTextView = (TextView)view.findViewById(R.id.textview);
        cv = (CardView)view.findViewById(R.id.cardview);

      //for whole cardview (If you want to click only card)
      view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Do the action.
            }
        });

    //if you want to click the only particular item in the CardView
    mImageView .setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               //Do the action.
            }
        });

    }
}

Try this snippet and let me know. I can solve it for you if it doesn't work.

The problem is your interface is the part of the adapter class while your onclicklistener is part of the holder class . You need to call the clicklistener from the adapter onBindViewHolder .For that purpose you have to give the id to the root layout of the itemholder layout file , and find view by id in itemholder constructor .After that you can call clicklistener as below.

 @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        Log.d("position", position+"");

        holder.mTextView.setText(mDataset.get(position).text);
        holder.mImageView.setImageResource(mDataset.get(position).img);
        holder.view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mClickListener.onItemClick(v, position)
        }
    });
    }

Simply add these lines give below in onBindViewHolder you already added this

cv = (CardView)view.findViewById(R.id.cardview);

line so it work or make sure you give CardView in xml id that name is cardview

cv = (CardView)view.findViewById(R.id.cardview);

holder.cv.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mClickListener.onItemClick(v, position)
        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM