Ahtisham
Ahtisham

Reputation: 10116

How to get a reference of next RecyclerView item

I have created a RecyclerView with alternating row color like this:

enter image description here

Whenever I delete an row from the list say for example I delete row whose product name is cookies my list gets updated like this:

enter image description here

as you can see the updated list no longer supports alternating row color. The simple solution would be to change the background color of next View (row) after deleting the current View. For that I first need a reference of next View but as a beginner in android I don't know how to get it.

Adapter:

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

    private List<Model> originalList;
    
    Adapter(List<Model> list){ originalList = list; }

    @Override
    public void onBindViewHolder(final Adapter.ViewHolder holder, final int position) {
        
        Model list = originalList.get(position);
        
        if (position % 2 == 1)
            holder.itemView.setBackgroundColor(Color.parseColor("#e9e9e9"));

        final View holder.nextItemView = ? // how to get reference to next View here  

        holder.product.setText(list.getName());
        holder.price.setText(String.valueOf(list.getPrice()));
        holder.quantity.setText(String.valueOf(list.getQuantity()));            
        holder.options.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showPopupMenu(holder.options, nextItemView, position);
            }
        });
    }

    private void showPopupMenu(View options, final View view, final int position){
        final PopupMenu popup = new PopupMenu(options.getContext(), options);
        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.options_menu, popup.getMenu());
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                String menuItem = item.toString();
                if (menuItem.equals("Delete")){                  
                     originalList.remove(position);
                     notifyItemRemoved(position);
                     int count = originalList.size();
                     if (count != 0){
                           int color = Color.TRANSPARENT;
                           Drawable background = view.getBackground();
                           if (background instanceof ColorDrawable)
                               color = ((ColorDrawable) background).getColor();         
                           if (color == Color.parseColor(#e9e9e9))
                              color = Color.TRANSPARENT;

                           view.setBackground(color); 
                     }  
                }
                return true;
            }
        });
        popup.show();
    }
}    

options is a ImageButton on the click of which I show a popup menu with item labelled as Delete on click of which the row gets deleted from the list.

Upvotes: 1

Views: 631

Answers (2)

codegames
codegames

Reputation: 1921

when an item removed. background of all items after that need to be updated.

Method 1

so after you remove item with position of p from list of itemList and notify it you have to do this.

if (itemList.size - p > 0)
    notifyItemRangeChanged(p, itemList.size - p)

Method 2

at this point it should work but it can be more optimized. you need just change background but now it will call onBindViewHolder for each items after p.

you can use payload to just change background and do nothing more.

add a const value:

const val PAYLOAD_BACKGROUND = 10

change first method code into this. it says that only update background.

if (itemList.size - p > 0)
    notifyItemRangeChanged(p, itemList.size - p, PAYLOAD_BACKGROUND)

override this method

onBindViewHolder(holder, position, payloads)

after you implemented this method the previous onBindViewHolder method will not call anymore. and you have to do all of that inside this method.

onBindViewHolder(holder, position, payloads) {

    if (payloads.contains(PAYLOAD_BACKGROUND) || payloads.isEmpty()) {
        // set background color
    }

    if (payloads.isEmpty()) {
        // do anything else that you were doing inside onBindViewHolder
    }

}

if payloads is not empty it means this is a partial update. but if payloads is empty means this is a complete update like the old onBindViewHolder

Upvotes: 0

Mohammed Alaa
Mohammed Alaa

Reputation: 3320

Quick fix you can call notifyDataSetChanged() instead of notifyItemRemoved(position) and add an else part

if (position % 2 == 1)
     holder.itemView.setBackgroundColor(Color.parseColor("#e9e9e9")); // gray
else
     holder.itemView.setBackgroundColor(Color.parseColor("#ffffff")); // white

but this solution will do heavy operations if your list contains a lot of items


the solution which I recommend is using ListAdapter with DiffUtil which will trigger the operation for the only modified items , you can find a sample for it here link1 ,link2, link3

Upvotes: 2

Related Questions