sziraqui
sziraqui

Reputation: 6112

Call notifyItemChanged(int position) or equivalent from RecyclerView.ViewHolder

My RecyclerView items contains views that have 4 TextViews. I "collapse" and "expand" each view item by setting 2 TextViews' View.visibility to View.GONE and View.VISIBILITY respectively by implementing onClick(View view). I know I must call notifyItemChanged(int position) function of my RecyclerView adapter after a collapse/expand but the problem is that position of view item cannot be (normally) accessed from its ViewHolder.

As a workaround, I have created a 5th TextView in a view item to hold the position of the item. I access this textview from the view passed to onClick() and thus get the position of the item that I use to call notifyItemChanged(position) and update the screen.

My solution works but I am looking for a cleaner solution. Using a view to save item position is definitely not good idea

Here's the important parts of my code:

public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.NotificationHolder> {
    Context context;
    List<Notification> notifications;
    // Notification is my custom class (POJO)
    public NotificationAdapter(Context context, List<Notification> notificationList) {
        this.context = context;
        this.notifications = notificationList;
    }
    public class NotificationHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        View view;
        //The 4 TextViews
        TextView titleTv, descTv, timeTv,extraTv;
        //TextView added to hold position of the view item
        TextView positionJugad;
        public NotificationHolder(View itemView) {
            super(itemView);
            titleTv = itemView.findViewById(R.id.notification_subject_tv);
            descTv = itemView.findViewById(R.id.notification_body_tv);
            timeTv = itemView.findViewById(R.id.notification_time_tv);
            extraTv = itemView.findViewById(R.id.notification_extra_info_tv);
            positionJugad = itemView.findViewById(R.id.notification_view_position);
            itemView.setOnClickListener(this);
            this.view = itemView;
        }
        public void bindNotification(Notification notification, int position){
            titleTv.setText(notification.getTitle());
            descTv.setText(notification.getDescription());
            timeTv.setText(notification.getTime();
            extraTv.setText(notification.getExtra());
            positionJugad.setText(""+position);
        }
        public void collapseView(){
            descTv.setVisibility(View.GONE);
            extraTv.setVisibility(View.GONE);
        }
        public void expandView(){
            descTv.setVisibility(View.VISIBLE);
            extraTv.setVisibility(View.VISIBLE);
        }
        @Override
        public void onClick(View view){
            //get the textview that stores position
            TextView jugad = view.findViewById(R.id.notification_view_position);
            if(descTv.getVisibility()==View.GONE){
                expandView();
            }
            else collapseView();
            notifyViewToggle(Integer.parseInt(jugad.getText().toString()));
        }
    }
    @Override
    public NotificationHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.notification_item,parent,false);
        return new NotificationHolder(view);
    }

    @Override
    public void onBindViewHolder(NotificationHolder holder, int position) {
        Notification notification = notifications.get(position);
        holder.bindNotification(notification,position);
    }
    //To change view state from collapsed to expanded and vice versa
    public void notifyViewToggle(int position){

            notifyItemChanged(position);
    }

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

Upvotes: 2

Views: 2334

Answers (1)

vikas kumar
vikas kumar

Reputation: 11018

you don't have to use another text view to store the position. instead, use

getAdapterPosition()

which gives you the current adapter position.

your onClick should look like this

@Override
        public void onClick(View view){
            if(descTv.getVisibility()==View.GONE){
                expandView();
            }
            else collapseView();
            notifyViewToggle(getAdapterPosition());
        }

and modify notifyViewToggle to this

notifyViewToggle(int position)

Upvotes: 3

Related Questions