1

I'm trying to change the background color of the clicked item in RecyclerView from the adapter and it works, but the problem is when I click on position 1 it changes the color of position 1 and 7, and when I click on position 2 it changes the color of position 2 and 8 and so on ...

public class RecyclerViewAdapter extends 
RecyclerView.Adapter<RecyclerViewAdapter.viewHolder> {

    private ArrayList<String> name = new ArrayList<>();
    private Context context;
    boolean added = false;

    public RecyclerViewAdapter(ArrayList<String> name, Context context) {
        this.name = name;
        this.context = context;
    }

    @Override
    public viewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_horizontal_listview, parent, false);

        return new viewHolder(view);
    }

    @Override
    public void onBindViewHolder(final viewHolder holder, final int position) {
    holder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {

                final Dialog dialog = new Dialog(view.getContext());
                dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                dialog.setCancelable(false);
                dialog.setContentView(R.layout.add_item_dialog_small);
                Window window = dialog.getWindow();
                window.setLayout(500, 450);

                Button addToList = (Button) dialog.findViewById(R.id.addToList);
                addToList.setOnClickListener(new View.OnClickListener() {
                    @SuppressLint("ResourceAsColor")
                    @Override
                    public void onClick(View v) {

                        holder.cardView.setBackgroundColor(R.color.layer4);

                        dialog.dismiss();
                    }
                });

                dialog.show();

            }
        });

}

Edit: here is the cardView :

    <android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cardView"
    android:layout_width="300dp"
    android:layout_height="320dp"
    android:layout_margin="10dp"
    android:background="@color/layer2"
    card_view:cardCornerRadius="2dp">

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="2dp"
        android:background="@color/layer3"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal"
            android:padding="5dp">

            <TextView
                android:id="@+id/textViewItemName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Test Item"
                android:textColor="@color/add_button"
                android:textSize="25sp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="left"
            android:orientation="horizontal"
            android:padding="5dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/item_number"
                android:textColor="@color/text_view_color"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/textViewItemNumber"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginLeft="10dp"
                android:textColor="@color/second_color"
                android:textSize="20sp" />

        </LinearLayout>

    </LinearLayout>
</android.support.v7.widget.CardView>
Sundos Altamimi
  • 29
  • 1
  • 1
  • 12

4 Answers4

2

In case of implementing options (such as favorite icon, checkbox, highlight or ...) to each row of a recyclerview, i think the best way is to create an object with your arbitrary parameter. for example for favorite a boolean parameter is best choice.

In your case you should create an object with a string and a boolean parameter with their setters and getters like below:

public class mObject {
   private String name;
   private boolean clicked;

        // setters and getters
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public boolean isClicked() {
            return clicked;
        }

        public void setClicked(boolean clicked) {
            this.clicked = clicked;
        }
}

and then set your data in a list of this object then pass it to the adapter. In onBindViewHolder, first check click value, if is true change the color. then in onClick method do both change the boolean value and background color and finally use notifyDataSetChanged(); for updating view. Your adapter onBindViewHolder should looks like below:

@Override
        public void onBindViewHolder(RecyclerView.ViewHolder view,final int position) {

            final MVH holder = (MVH) view;
            holder.tv.setText(name.get(position).getName());

            if (name.get(position).isClicked()){
                holder.tv.setBackgroundColor(context.getResources().getColor(R.color.colorPrimary));
            } else {
                holder.tv.setBackgroundColor(context.getResources().getColor(R.color.colorAccent));
            }
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View view) {

                    final Dialog dialog = new Dialog(context);
                    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                    dialog.setCancelable(false);
                    dialog.setContentView(R.layout.add_item_dialog_small);
                    Window window = dialog.getWindow();
                    window.setLayout(500, 450);
                    Button addToList = (Button) dialog.findViewById(R.id.addToList);
                    addToList.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {

                            if (name.get(position).isClicked()){
                                name.get(position).setClicked(false);
                                holder.tv.setBackgroundColor(context.getResources().getColor(R.color.colorPrimary));
                            } else {
                                name.get(position).setClicked(true);
                                holder.tv.setBackgroundColor(context.getResources().getColor(R.color.colorAccent));
                            }
                            dialog.dismiss();
                            notifyDataSetChanged();
                        }
                    });

                    dialog.show();

                }
            });
        }
Sina Khorshidian
  • 222
  • 2
  • 17
0

You can simplyfy your code using lambdas, that's for sure.

This:

addToList.setOnClickListener(new View.OnClickListener() {
                @SuppressLint("ResourceAsColor")
                @Override
                public void onClick(View v) {

                    holder.cardView.setBackgroundColor(R.color.layer4);

                }
                    dialog.dismiss();
                }
            });

You can change to:

addToList.setOnClickListener((View v) -> {

                        holder.cardView.setBackgroundColor(R.color.layer4);

                    }
                        dialog.dismiss();
                    }
                });
0

store var positionClicked in your adapter so it will be

onClick{positionClicked = position) 

and then in your onBindViewHolder put

if(positionClicked==position){
  //change color of element here// 
} 
pb4now
  • 1,305
  • 4
  • 18
  • 45
  • but how to get the position in adapter? I mean I get the position from within the onBindViewHolder only !! – Sundos Altamimi Jul 28 '18 at 08:03
  • you put both snips of code in "onBindViewHolder" -there U have posiiton...get it? – pb4now Jul 28 '18 at 10:46
  • got it , the problem is it recycling the item with its background color when scroll it away , I think it is not matter of position :/ – Sundos Altamimi Jul 28 '18 at 11:44
  • yeah , exacly it is the same element but bc it is recyclerview it seams to highlight two elements- by storing position U will be able to style element depending on position in array and not depending on viewHolder(which can be recycled) - let me know if U made it to work(y) – pb4now Jul 28 '18 at 12:48
  • can you please show it in answer , Im getting confused of this but it seems like you are confident of it – Sundos Altamimi Jul 28 '18 at 12:59
0

I face this problem also. What you can do is set the background colour before click in onBindViewHolder method.

@Override
public void onBindViewHolder(final viewHolder holder, final int position) {

holder.cardView.setBackgroundColor(R.color.defaultBackgroundColour);    
Yang
  • 11
  • 4