1
votes

So I have a pretty simple recycler view. And a apply button. When the button it pressed the text turns Orange. But when I scroll down , I see that there are other items who's apply button color has been changed too.

Does anyone know what's happening ? Here are a few code snippets.

public void apply(View view){
    Button b = (Button)view;
    b.setTextColor(ColorEx.TUTOR_BEAR_LOGO_ORANGE);
}

That's the method being executed in the main activity. This is the buttons xml which is in a different layout. (item layout)

  <Button
    android:id="@+id/btn_apply"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="APPLY"
    android:onClick="apply"
  />

Here is my adapter class

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

Context context;
ArrayList<String> title;

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

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.item_sample,parent,false);
    MyViewHolder  holder = new MyViewHolder(view);
    return  holder;
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    switch (position){
        case 0:
        case 3:
        case 6:
            holder.imageView.setImageResource(R.drawable.x);
            break;
        case 1:
        case 4:
        case 7:
            holder.imageView.setImageResource( R.drawable.y);
            break;
        case 2:
        case 5:
            holder.imageView.setImageResource(R.drawable.z);
            break;
        case 8:
            holder.imageView.setImageResource(R.drawable.z);
            break;
    }
}

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



class MyViewHolder extends RecyclerView.ViewHolder{
    ImageView imageView;
    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        imageView = itemView.findViewById(R.id.imageView);
    }
}

}

I screen recorded the incident and uploaded it as a .gif for better reference. Here is the link below. https://media.giphy.com/media/jOagjkf9dmW5Kvrqyn/giphy.gif

2
Post your adapter - Uuu Uuu
Adapter Posted. - Tanzim Chowdhury
@TanzimChowdhury As you might be knowing that Recyclerview recycle's the view so the same view is recycled and used for other views that is why you are facing this issue. To solve this you need to keep a track of the position at which the button was clicked and change the color accordingly in your onBindviewHolder. - Rajat Beck
Could you post an example code please ? - Tanzim Chowdhury

2 Answers

1
votes
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
 import java.util.List;

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

final Context context;
final ArrayList<String> title;
final List<Boolean> buttonPositionList;//this tells weather the button is selected or not


public Adapter(Context context, ArrayList<String> title,List<Boolean> buttonPositionList) {
    this.context = context;
    this.buttonPositionList = buttonPositionList;
    this.title = title;
}



@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.item_sample,parent,false);
    MyViewHolder  holder = new MyViewHolder(view);
    holder.btnApply.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            buttonPositionList.set(holder.getAdapterPosition(),!buttonPositionList.get(holder.getAdapterPosition()));
            notifyDataSetChanged();// or notify Item set changed
        }
    });
    return  holder;
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    switch (position){
        case 0:
        case 3:
        case 6:
            holder.imageView.setImageResource(R.drawable.x);
            break;
        case 1:
        case 4:
        case 7:
            holder.imageView.setImageResource( R.drawable.y);
            break;
        case 2:
        case 5:
            holder.imageView.setImageResource(R.drawable.z);
            break;
        case 8:
            holder.imageView.setImageResource(R.drawable.z);
            break;
    }
    // Button Position is selected
    if(buttonPositionList.get(position)){
        holder.btnApply.setTextColor(ColorEx.TUTOR_BEAR_LOGO_ORANGE);
    }else{
        //The color you want when not selected
    }
}

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

protected class MyViewHolder extends RecyclerView.ViewHolder{
    ImageView imageView;
    Button btnApply;
    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        imageView = itemView.findViewById(R.id.imageView);
        btnApply = itemView.findViewById(R.id.btn_apply);
    }
}

}

1
votes

You have to save item's position that was clicked

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

    Context context;
    ArrayList<String> title;
    Set<Integer> itemClicked;

    public Adapter(Context context, ArrayList<String> title) {
        this.context = context;
        this.title = title;
        this.itemClicked = new HashSet<>();
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.item_sample, parent, false);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {
        switch (position) {
            case 0:
            case 3:
            case 6:
                holder.imageView.setImageResource(R.drawable.x);
                break;
            case 1:
            case 4:
            case 7:
                holder.imageView.setImageResource(R.drawable.y);
                break;
            case 2:
            case 5:
                holder.imageView.setImageResource(R.drawable.z);
                break;
            case 8:
                holder.imageView.setImageResource(R.drawable.z);
                break;
        }

        if (itemClicked.contains(position)) {
            holder.button.setTextColor(ColorEx.TUTOR_BEAR_LOGO_ORANGE);
        } else {
            holder.button.setTextColor(ColorEx.BLACK);
        }

        holder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (itemClicked.contains(position)) {
                    itemClicked.remove(position);
                } else {
                    itemClicked.add(position);
                }
                notifyItemChanged(position);
            }
        });
    }

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


    class MyViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;
        Button button;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView);
            button = itemView.findViewById(R.id.btn_apply);
        }
    }
}