Search code examples
androidandroid-intentandroid-recyclerviewpopupmenu

Retrieve Clicked Item Position and Details from RecyclerView in Adapter Class


I'm developing an Android app where I have a RecyclerView displaying a list of movies. Each item in the list has an icon that, when clicked, opens a PopupMenu with options to add the movie or view its details. I'm trying to retrieve the position of the clicked item in the RecyclerView and use this position to fetch details such as title, date, overview, and poster path from the resultList.

Here's my RecyclerViewAdapter class:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements PopupMenu.OnMenuItemClickListener {

    public ArrayList<MovieModel.Results> resultList;
    public Context context;


    public RecyclerViewAdapter(ArrayList<MovieModel.Results> list, Context context) {
        this.resultList = list;
        this.context = context;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        ImageView posterImage;
        ImageView addIcon;
        TextView movieName;
        TextView date;
        TextView overview;

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

            posterImage = itemView.findViewById(R.id.movie_poster);
            addIcon = itemView.findViewById(R.id.addImage);
            movieName = itemView.findViewById(R.id.movieNameText);
            date = itemView.findViewById(R.id.dateText);
            overview = itemView.findViewById(R.id.overviewText);

        }
    }


    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_2, parent, false);
        return new ViewHolder(itemView);
    }


    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        if (position < getItemCount()) {
            String title = resultList.get(position).getTitle();
            String date = resultList.get(position).getRelease_date();
            String overview = resultList.get(position).getOverview();
            String posterPath = resultList.get(position).getPoster_path();

            holder.movieName.setText(title);
            holder.date.setText(date);
            holder.overview.setText(overview);

            if (posterPath == null) {
                holder.posterImage.setImageDrawable(context.getDrawable(R.drawable.no_poster));
            } else {
                Glide.with(context).load(FeedActivity.BASE_PHOTO_URL + posterPath).into(holder.posterImage);
            }


            int finalPosition = position;
            holder.addIcon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //Toast.makeText(context, "You clicked : " + finalPosition, Toast.LENGTH_SHORT).show();

                    showPopup(v);
                }
            });
        }
        position++;
    }


    private void showPopup(View v) {

        PopupMenu popup = new PopupMenu(context,v);
        popup.setOnMenuItemClickListener(this);
        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.menu, popup.getMenu());
        popup.show();

    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {

        // Here I need to position of clicked item in Recyclerview, and I will get title, date etc.

        int pos;

        if(item.getItemId() == R.id.menuAdd){

            // Find here to get position of clicked movie.
            String title = resultList.get(pos).getTitle();
            String date = resultList.get(pos).getRelease_date();
            String overview = resultList.get(pos).getOverview();
            String posterpath = resultList.get(pos).getPoster_path();

            Intent intent1 = new Intent(context,ListActivity.class);
            intent1.putExtra("title",title);
            intent1.putExtra("date",date);
            intent1.putExtra("overview",overview);
            intent1.putExtra("posterpath",posterpath);
            context.startActivity(intent1);
            return true;

        }
        else if(item.getItemId() == R.id.menuShowDetails){

            int movieId = resultList.get(pos).getMovieId();

            Intent intent1 = new Intent(context, MovieDetails.class);
            intent1.putExtra("movie_id",movieId);
            context.startActivity(intent1);
            return true;

        }

        return false;
    }


    @Override
    public int getItemCount() {
        return resultList.size();
    }

}

Questions:

  1. How can I correctly retrieve the position of the clicked item in the RecyclerView from my onMenuItemClick method in the RecyclerViewAdapter class?

  2. Is there a better approach to handle item clicks and pass item details to different activities when using PopupMenu within a RecyclerView adapter?

Any suggestions or improvements would be greatly appreciated! Thank you!


Solution

  • You can use the ViewHolder's getAdapterPosition() to retrieve the item's position within an interface method. Then store the clicked position in a member variable.

    Additionally, there shouldn't be a need to call position++ from within your onBindViewHolder.

    // Create a member variable to store the clicked position
    public int clickedPos = -1;
    
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        
        // ...
        
        holder.addIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // When you're inside the click listener interface,
                // you can access the position using the ViewHolder.
                // We'll store the position in the member variable in this case.
                clickedPos = holder.getAdapterPosition();
            }
        });
        
        // Remove the 'position++' call as the position should already be handled without explicitly updating it.
    }
    
    @Override
    public boolean onMenuItemClick(MenuItem item) {
        // You can use clickedPos here to perform whatever tasks you need.
        
        // ...
    }