Android Adapter doesn't work when selecting multiple cardviews - java

I have a problem, I don't understand why my CardViews have this effect.
I need select one or more CardViews but my adapter does not work fine. Is my implementation of the adapter incorrect?
My Adapter
public class PersonasAdapter extends RecyclerView.Adapter < PersonasAdapter.PersonasViewHolder > {
private Persona subject;
private List < Persona > personastList;
public PersonasAdapter() {}
public PersonasAdapter(List < Persona > personastList) {
this.personastList = personastList;
}
#Override
public void onBindViewHolder(final PersonasViewHolder personasViewHolder, int i) {
Persona ci = personastList.get(i);
personasViewHolder.txtNombre.setText(ci.getNombre());
personasViewHolder.txtUsuario.setText(ci.getUsuario());
personasViewHolder.txtTwitter.setText(ci.getTwitter());
subject = personastList.get(i);
personasViewHolder.card_view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(v.getContext(), "Eliminar Cardview", Toast.LENGTH_SHORT).show();
personasViewHolder.card_view.setBackgroundResource(R.color.colorPrimary);
return false;
}
});
personasViewHolder.card_view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Reproducir", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public PersonasViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_layout_persona, viewGroup, false);
cardView
return new PersonasViewHolder(itemView);
}
Class Static
public static class PersonasViewHolder extends RecyclerView.ViewHolder {
protected TextView txtNombre;
protected TextView txtUsuario;
protected TextView txtTwitter;
protected CardView card_view;
public PersonasViewHolder(View v) {
super(v);
txtNombre = (TextView) v.findViewById(R.id.txtNombre);
txtUsuario = (TextView) v.findViewById(R.id.txtUsuario);
txtTwitter = (TextView) v.findViewById(R.id.txtTwitter);
card_view = (CardView) v.findViewById(R.id.card_view);
}
}
//Metodo que nos retornarta la cantidad de personas en la lista
#Override
public int getItemCount() {
return personastList.size();
}
}

The problem is the following:
You perfom a Long Click on the first PersonasViewHolder of your list.
Then, in your onLongClickListener, you change the background color of that holder.
But that holder is then re-used for later positions in the recycler-view, giving the sensation that the background is being repeated in later elements.
You can fix it by storing the state of each cardview in an array, and then binding the correct color for each position. I modified your code to show this idea:
public class PersonasAdapter extends RecyclerView.Adapter < PersonasAdapter.PersonasViewHolder > {
private Persona subject;
private List < Persona > personastList;
private boolean[] selectedPersonas;
public PersonasAdapter() {}
public PersonasAdapter(List < Persona > personastList) {
this.personastList = personastList;
this.selectedPersonas = new boolean[personasList.size()];
for (int i = 0; i < personasList.size(); i++) {
this.selectedPersonas[i] = false;
}
}
#Override
public void onBindViewHolder(final PersonasViewHolder personasViewHolder, final int i) {
Persona ci = personastList.get(i);
personasViewHolder.txtNombre.setText(ci.getNombre());
personasViewHolder.txtUsuario.setText(ci.getUsuario());
personasViewHolder.txtTwitter.setText(ci.getTwitter());
subject = personastList.get(i);
updatePersonaHolderBackground(personaViewHolder, i);
personasViewHolder.card_view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(v.getContext(), "Eliminar Cardview", Toast.LENGTH_SHORT).show();
selectedPersonas[i] = !selectedPersonas[i];
updatePersonaHolderBackground(personaViewHolder, i);
return false;
}
});
personasViewHolder.card_view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Reproducir", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public PersonasViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_layout_persona, viewGroup, false);
cardView
return new PersonasViewHolder(itemView);
}
private void updatePersonaHolderBackground(final PersonasViewHolder personasViewHolder, final int i) {
if (selectedPersonas[i]) {
personasViewHolder.card_view.setBackgroundResource(R.color.colorPrimary);
} else {
// TODO: change the color of personasViewHolder back to normal using whatever color you want.
}
}

I solved my problem.
The problem are the position the cardview.
i declare global variable
int globalPosition;
and
personasViewHolder.card_view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(v.getContext(), "Eliminar Cardview", Toast.LENGTH_SHORT).show();
personasViewHolder.card_view.setBackgroundResource(R.color.colorPrimary);
globalPosition=i;
notifyDataSetChanged();
return false;
}
});
and a validation in
and a if in onBindViewHolder
if (i == globalPosition) {
personasViewHolder.card_view.setBackgroundResource(R.color.colorPrimary);
} else {
personasViewHolder.card_view.setBackgroundResource(R.color.colorAccent);
}
and the result it's this.
public class PersonasAdapter extends RecyclerView.Adapter < PersonasAdapter.PersonasViewHolder > {
private Persona subject;
private List < Persona > personastList;
public PersonasAdapter() {}
int globalPosition;
public PersonasAdapter(List < Persona > personastList) {
this.personastList = personastList;
}
#Override
public void onBindViewHolder(final PersonasViewHolder personasViewHolder, final int i) {
Persona ci = personastList.get(i);
personasViewHolder.txtNombre.setText(ci.getNombre());
personasViewHolder.txtUsuario.setText(ci.getUsuario());
personasViewHolder.txtTwitter.setText(ci.getTwitter());
subject = personastList.get(i);
personasViewHolder.card_view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(v.getContext(), "Eliminar Cardview", Toast.LENGTH_SHORT).show();
personasViewHolder.card_view.setBackgroundResource(R.color.colorPrimary);
globalPosition=i;
notifyDataSetChanged();
return false;
}
});
personasViewHolder.card_view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Reproducir", Toast.LENGTH_SHORT).show();
}
});
if(i==globalPosition)
{
//change color like
personasViewHolder.card_view.setBackgroundResource(R.color.colorPrimary);
}
else
{
personasViewHolder.card_view.setBackgroundResource(R.color.colorAccent);
}
}
#Override
public PersonasViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_layout_persona, viewGroup, false);
return new PersonasViewHolder(itemView);
}
public static class PersonasViewHolder extends RecyclerView.ViewHolder {
protected TextView txtNombre;
protected TextView txtUsuario;
protected TextView txtTwitter;
protected CardView card_view;
public PersonasViewHolder(View v) {
super(v);
txtNombre = (TextView) v.findViewById(R.id.txtNombre);
txtUsuario = (TextView) v.findViewById(R.id.txtUsuario);
txtTwitter = (TextView) v.findViewById(R.id.txtTwitter);
card_view = (CardView) v.findViewById(R.id.card_view);
}
}
//Metodo que nos retornarta la cantidad de personas en la lista
#Override
public int getItemCount() {
return personastList.size();
}
}

Related

How to highlight a selected RecyclerView item and use its values in Activity

I have a list of words with translations in RecyclerView. I want the selected word to be highlighted, but at the same time I could use these values in Activity. I can highlight selected values or use the values of a selected item, but the combination of the both fails.
Please, maybe You see where I am wrong and can help solve my problem.
p.s. Please don’t judge me for the not enough clean code and my English, I’m learning. :)
MyListActivity.java
public class MyListActivity extends AppCompatActivity {
public ArrayList<MyWord> myWordList = new ArrayList<>();
SelectData sd = new SelectData();
int wordId;
String word;
String translation;
public RecyclerView mRecycleView;
public MyAdapter mAdapter;
public RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_list);
sd.selectMyWords(myWordList);
buildRecycleView();
Button btnInsert = findViewById(R.id.mywords_button_insert);
Button btnEdit = findViewById(R.id.mywords_button_edit);
Button btnDelete = findViewById(R.id.mywords_button_delete);
Button btnMain = findViewById(R.id.mywords_button_backttomain);
mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
// **This is my selected item values**
wordId = myWordList.get(position).getWordId();
word = myWordList.get(position).getWord();
translation = myWordList.get(position).getTranslation();
Toast.makeText(MyListActivity.this, "Selected -> " + word, Toast.LENGTH_SHORT).show();
}
});
btnEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!(word == null)) {
Intent intentInsert = new Intent(MyListActivity.this, InsertActivity.class);
intentInsert.putExtra("W", word);
intentInsert.putExtra("TR", translation);
intentInsert.putExtra("ACTION", "ED");
startActivity(intentInsert);
} else {
Toast.makeText(MyListActivity.this, "Select word", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
public void buildRecycleView(){
mRecycleView = findViewById(R.id.mywords_RecycleView);
mRecycleView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new MyAdapter(myWordList);
mRecycleView.setLayoutManager(mLayoutManager);
mRecycleView.setAdapter(mAdapter);
if (myWordList.isEmpty()){
Toast.makeText(this, "word list is empty", Toast.LENGTH_SHORT).show();
}
}
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<MyWord> mMyWordList;
private OnItemClickListener mListener;
public interface OnItemClickListener{
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mTextViewEN;
public TextView mTextViewLT;
public ImageView imageViewLearned;
public MyViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mTextViewEN = itemView.findViewById(R.id.myList_textView_word);
mTextViewLT = itemView.findViewById(R.id.myList_textView_translation);
imageViewLearned = itemView.findViewById(R.id.iV_learned);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
listener.onItemClick(position);
}
}
}
});
}
}
public MyAdapter(ArrayList<MyWord> myWordList){
mMyWordList = myWordList;
}
int selectedItem = -1;
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_list_view_layout, parent, false);
MyViewHolder mvh = new MyViewHolder(v, mListener);
return mvh;
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, final int position) {
MyWord currentMyWord = mMyWordList.get(position);
holder.mTextViewEN.setText(currentMyWord.getWord());
holder.mTextViewLT.setText(currentMyWord.getTranslation());
// TODO - START (select item highlight) - if I activate highlighting, the assignment of values no longer works in MyListActivity.
/* holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedItem = position;
notifyDataSetChanged();
}
});
if (selectedItem == position) {
holder.itemView.setBackgroundColor(Color.parseColor("#C0C0C0"));
} else {
holder.itemView.setBackgroundColor(Color.parseColor("#F8F8F8"));
} */
//TODO -END
}
#Override
public int getItemCount() {
return mMyWordList.size();
}
}
Looks like your commented code would overwrite your click listener with one that only hightlights. Try combining them:
public MyViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mTextViewEN = itemView.findViewById(R.id.myList_textView_word);
mTextViewLT = itemView.findViewById(R.id.myList_textView_translation);
imageViewLearned = itemView.findViewById(R.id.iV_learned);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
selectedItem = position;
notifyDataSetChanged();
listener.onItemClick(position);
}
}
}
});
}

How to manage multiple positions in RecyclerView OnClickListener

I want to know how I can get access to other elements of the array in this onclicklistener for a Recycler view. Specifically, I want to be able to change the enabled state of a position other than the current Listener position, but within the click event.
I'm trying to make it such that if three colors are checked (those are check boxes) every box not checked will be disabled until the number of boxes checked is < 3.
The for-loops I have I wrote make sense, but I can't programmatically change the enabled state within the onClickListener for some reason.
private void buildRecyclerView() {
mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new ExampleAdapter(mExampleList);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
boolean checkedState;
if (mExampleList.get(position).getChecked1() == false) {
checkedState = true;
} else {
checkedState = false;
}
changeItem(position, checkedState);
int sum = 0;
for (int i = 0; i < stringArray.length; i++) {
Boolean checked = mExampleList.get(i).getChecked1();
if (checked == true) {
sum = sum + 1;
}
}
for (int i = 0; i < stringArray.length; i++) {
Boolean checked = mExampleList.get(i).getChecked1();
if (!checked && sum == 3) {
mExampleList.get(i).setEnabled1(false);
} else {
mExampleList.get(i).setEnabled1(true);
}
}
}
});
}
adapter
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {
private ArrayList<ExampleItem> mExampleList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public CheckBox mCheckBox;
public ExampleViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mCheckBox = itemView.findViewById(R.id.checkBox);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION);
listener.onItemClick(position);
}
}
});
}
}
public ExampleAdapter(ArrayList<ExampleItem> exampleList) {
mExampleList = exampleList;
}
#NonNull
#Override
public ExampleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.example_item, parent, false);
ExampleViewHolder evh = new ExampleViewHolder(v, mListener);
return evh;
}
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
holder.mCheckBox.setText(currentItem.getCheckText());
holder.mCheckBox.setEnabled(currentItem.getEnabled1());
holder.mCheckBox.setChecked(currentItem.getChecked1());
}
#Override
public int getItemCount() {
return mExampleList.size();
}
}
Item Class
public class ExampleItem {
public String mCheckText;
public Boolean mEnabled;
public Boolean mChecked;
public ExampleItem(String mCheckText, Boolean mEnabled, Boolean mChecked) {
this.mCheckText = mCheckText;
this.mEnabled = mEnabled;
this.mChecked = mChecked;
}
public ExampleItem(String mCheckText) {
this.mCheckText = mCheckText;
}
public String getCheckText() {
return mCheckText;
}
public void setCheckText(String mCheckText) {
this.mCheckText = mCheckText;
}
public Boolean getEnabled1() {
return mEnabled;
}
public void setEnabled1(Boolean mEnabled) {
this.mEnabled = mEnabled;
}
public Boolean getChecked1() {
return mChecked;
}
public void setChecked1(Boolean mChecked) {
this.mChecked = mChecked;
}
}
In other words, I am trying to make everything below blue disabled until I uncheck Red, Green, or Blue!
Try the following:
In adapter, add below codes:
private int selectedCount = 0;
public int getSelectedCount() {
return selectedCount;
}
public void setSelectedCount(int selectedCount) {
this.selectedCount = selectedCount;
notifyDataSetChanged();
}
and change onBindViewHolder() to:
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
holder.mCheckBox.setText(currentItem.getCheckText());
holder.mCheckBox.setChecked(currentItem.getChecked1());
if ((selectedCount == 3)) holder.mCheckBox.setEnabled(currentItem.getChecked1());
else holder.mCheckBox.setEnabled(true);
}
Then in Activity/Fragment, change mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener()... to:
mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
boolean checkedState;
int selectedCount = mAdapter.getSelectedCount();
if ((selectedCount != 3) || (mExampleList.get(position).getChecked1())) {
if (mExampleList.get(position).getChecked1() == false) {
checkedState = true;
selectedCount++;
} else {
checkedState = false;
selectedCount--;
}
changeItem(position, checkedState);
mAdapter.setSelectedCount(selectedCount);
}
}
});
Pls note that no need to have mEnabled field in the ExampleItem class. Hope that helps!
Explanantion:
About the onClick:- This is because CheckBox totally covered the layout, so itemView cannot recieve the click event. About RecyclerView:- The idea is simple, after modified the data set [not list, here I refer to the mExampleList and also the selectedCount], then call notifyDataSetChanged() which will redraw all recycler item views.
You would need to create a setter function for your 'mExampleList' in your Adpater class, to update the dataset that the adapter is using. It obviously does not change anything, if you make changes to 'mExampleList' in your activity, without updating the list used by the Adapter.
So at the end of your click listener you would have something like that:
mAdapter.setExampleList(mExampleList)
mAdapter.notifyDataSetChanged()

How to prevent the duplication of `RecyclerView` when scrolling?

I am showing a love sign on my RecyclerView.
When user clicked the color of the love sign changes from default gray to red color but when I scrolled it is showing color in some other positions(not clicked). Also the clicked color changes to gray.
I found large number of solutions but nothing worked for me.
Please help.
I am giving you my codes
Featured Products class
public class FeaturedlistAdapter extends RecyclerView.Adapter<FeaturedlistAdapter.FeaturedView>
{
private Context context;
private List<Featured_data> featured_data;
public FeaturedlistAdapter(Context context, List<Featured_data> featured_data,MyAdapterListener myAdapterListener) {
this.context=context;
this.featured_data=featured_data;
this.onclickListener=myAdapterListener;
}
#NonNull
#Override
public FeaturedView onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.list_allbrands, viewGroup, false);
return new FeaturedView(view);
}
#Override
public void onBindViewHolder(#NonNull FeaturedView featuredView, int i) {
String price = featured_data.get(i).getProductPrice();
String name = featured_data.get(i).getProductName();
String quantity = featured_data.get(i).getProductQty();
featuredView.getTxt_brandname().setText(featured_data.get(i).getProductName());
String wishlist=featured_data.get(i).getWishlist();
Picasso.get().load(HomeConstants.BASE_URL + featured_data.get(i).getProductImage()).placeholder(R.drawable.whitebackground).into(featuredView.img_brand);
if (price != null && !price.equals("")) {
String total_price = price + " Rs";
featuredView.getTxt_brand_price().setText(total_price);
}
if (quantity != null && !quantity.equals("")) {
String total_quantity = quantity + " Items";
featuredView.getTxt_brand_item().setText(total_quantity);
}
if(wishlist!=null)
{
if(wishlist.equals("0"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
else if(wishlist.equals("1"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255,255,0,0));
featuredView.txt_count.setText("1");
}
}
else
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
}
#Override
public int getItemCount() {
return featured_data.size();
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
class FeaturedView extends RecyclerView.ViewHolder {
ImageView img_brand,img_wishlist;
TextView txt_brandname,txt_brand_price,txt_brand_item,txt_count;
public ImageView getImg_brand() {
return img_brand;
}
public ImageView getImg_wishlist() {
return img_wishlist;
}
public TextView getTxt_brandname() {
return txt_brandname;
}
public TextView getTxt_brand_price() {
return txt_brand_price;
}
public TextView getTxt_brand_item() {
return txt_brand_item;
}
public TextView getTxt_count() {
return txt_count;
}
FeaturedView(#NonNull View itemView) {
super(itemView);
img_brand=itemView.findViewById(R.id.img_brand);
img_wishlist=itemView.findViewById(R.id.img_wishlist);
txt_brandname=itemView.findViewById(R.id.txt_brandname);
txt_brand_price=itemView.findViewById(R.id.txt_brand_price);
txt_brand_item=itemView.findViewById(R.id.txt_brand_item);
txt_count=itemView.findViewById(R.id.txt_count);
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String value = txt_count.getText().toString();
if (value.equals("0")) {
img_wishlist.setColorFilter(Color.argb(255, 255, 0, 0));
txt_count.setText("1");
} else if (value.equals("1")) {
img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
txt_count.setText("0");
}
onclickListener.wishlistOnclick(v,getAdapterPosition());
}
});
img_brand.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onclickListener.brandOnClick(v,getAdapterPosition());
}
});
}
}
private MyAdapterListener onclickListener;
public interface MyAdapterListener
{
void wishlistOnclick(View view ,int position);
void brandOnClick(View view,int position);
}
}
You need to keep the state of the view by using SparseBooleanArray. It is because in RecylerView the item will be shown with the previous view (if exist), i.e the view will be recycled first before used. Hence the mean of RecyclerView.
You can do something like this:
First, in your Adapter, add the SparseBooleanArray to hold the flags (Please read the comment in the code):
public class FeaturedlistAdapter extends RecyclerView.Adapter<FeaturedlistAdapter.FeaturedView>
{
private Context context;
private List<Featured_data> featuredData;
private SparseBooleanArray mSelectedFlags;
public FeaturedlistAdapter(Context context, List<Featured_data> featured_data,MyAdapterListener myAdapterListener) {
...
// init the flag
mSparseBooleanArray = new SparseBooleanArray();
}
#Override
public void onBindViewHolder(#NonNull FeaturedView featuredView, int i) {
int position = featuredView.getAdapterPosition();
Featured_data data = featuredData.get(position);
// reset the state of the view each time the
// view get recycled by applying the flag.
if(mSelectedFlags.get(position)) {
// set the selected state, i.e red
} else {
// SparseBooleanArray.get(i) is false if not found
// set the unselected state, i.e grey
}
}
then in your ViewHolder, set the state when member view is clicked/selected:
class FeaturedView extends RecyclerView.ViewHolder {
...
FeaturedView(#NonNull View itemView) {
...
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
...
// save the selected state
mSparseBooleanArray.put(getAdapterPosition(), true);
}
...
}
}
Now the view selected/unselected state will be reset using the saved stated from your SparseBooleanArray flag holder.
Replace Following Code in your file and try
if(wishlist!=null)
{
if(wishlist.equals("1")) // change is here
{
featuredView.img_wishlist.setColorFilter(Color.argb((255,255,0,0));
featuredView.txt_count.setText("1");
}
else (wishlist.equals("0")) // change is here
{
featuredView.img_wishlist.setColorFilter(Color.argb(255,255,111,111));
featuredView.txt_count.setText("0");
}
}
else
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
Also for this
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
featured_data.get(getAdapterPosition).setWishlist(featured_data.get(getAdapterPosition).getWishlist().equals("0")?"1":"0");
notifyItemChanged(getAdapterPosition());
onclickListener.wishlistOnclick(v,getAdapterPosition());
}
});
public class FeaturedlistAdapter extends RecyclerView.Adapter<FeaturedlistAdapter.FeaturedView>
{
private Context context;
private List<Featured_data> featured_data;
private final SparseBooleanArray mSparseBooleanArray;
public FeaturedlistAdapter(Context context, List<Featured_data> featured_data,MyAdapterListener myAdapterListener) {
this.context=context;
this.featured_data=featured_data;
this.onclickListener=myAdapterListener;
// init the flag
mSparseBooleanArray = new SparseBooleanArray();
}
#NonNull
#Override
public FeaturedView onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.list_allbrands, viewGroup, false);
return new FeaturedView(view);
}
#Override
public void onBindViewHolder(#NonNull FeaturedView featuredView, int i) {
String price = featured_data.get(i).getProductPrice();
String name = featured_data.get(i).getProductName();
String quantity = featured_data.get(i).getProductQty();
featuredView.getTxt_brandname().setText(featured_data.get(i).getProductName());
String wishlist=featured_data.get(i).getWishlist();
Picasso.get().load(HomeConstants.BASE_URL + featured_data.get(i).getProductImage()).placeholder(R.drawable.whitebackground).into(featuredView.img_brand);
if (price != null && !price.equals("")) {
String total_price = price + " Rs";
featuredView.getTxt_brand_price().setText(total_price);
}
if (quantity != null && !quantity.equals("")) {
String total_quantity = quantity + " Items";
featuredView.getTxt_brand_item().setText(total_quantity);
}
if(wishlist!=null)
{
if(wishlist.equals("0"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
else if(wishlist.equals("1"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255,255,0,0));
featuredView.txt_count.setText("1");
}
}
int position=featuredView.getAdapterPosition();
if(mSparseBooleanArray.get(position))
{
String value = featuredView.txt_count.getText().toString();
if (value.equals("0")) {
featuredView.img_wishlist.setColorFilter(Color.argb(255, 255, 0, 0));
// save the selected state
}
else if (value.equals("1")) {
featuredView.img_wishlist.setColorFilter(Color.argb(255,211,211,211));
// save the selected state
}
}
}
#Override
public int getItemCount() {
return featured_data.size();
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
class FeaturedView extends RecyclerView.ViewHolder {
ImageView img_brand,img_wishlist;
TextView txt_brandname,txt_brand_price,txt_brand_item,txt_count;
public ImageView getImg_brand() {
return img_brand;
}
public ImageView getImg_wishlist() {
return img_wishlist;
}
public TextView getTxt_brandname() {
return txt_brandname;
}
public TextView getTxt_brand_price() {
return txt_brand_price;
}
public TextView getTxt_brand_item() {
return txt_brand_item;
}
public TextView getTxt_count() {
return txt_count;
}
FeaturedView(#NonNull View itemView) {
super(itemView);
img_brand=itemView.findViewById(R.id.img_brand);
img_wishlist=itemView.findViewById(R.id.img_wishlist);
txt_brandname=itemView.findViewById(R.id.txt_brandname);
txt_brand_price=itemView.findViewById(R.id.txt_brand_price);
txt_brand_item=itemView.findViewById(R.id.txt_brand_item);
txt_count=itemView.findViewById(R.id.txt_count);
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String value = txt_count.getText().toString();
if (value.equals("0")) {
img_wishlist.setColorFilter(Color.argb(255, 255, 0, 0));
txt_count.setText("1");
} else if (value.equals("1")) {
img_wishlist.setColorFilter(Color.argb(255,211,211,211));
txt_count.setText("0");
}
onclickListener.wishlistOnclick(v,getAdapterPosition());
mSparseBooleanArray.put(getAdapterPosition(), true);
notifyDataSetChanged();
}
});
img_brand.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onclickListener.brandOnClick(v,getAdapterPosition());
}
});
}
}
private MyAdapterListener onclickListener;
public interface MyAdapterListener
{
void wishlistOnclick(View view ,int position);
void brandOnClick(View view,int position);
}
}

Multi selection in RecyclerView?

Hello I am trying to implement multi select in recycler view android for showing an icon when clicked on that particular view, I have tried the below code and is working fine for that particular position, however there are other several views that too are getting updated, so please check and let me know what am I missing
Here is my adapter code:
public class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
Context context;
ArrayList<String> alContactName, alContactEmail, alContactNumber;
ArrayList<Boolean> alFromLinkedIn;
int mergeFlag=0;
private static SparseBooleanArray selectedItems;
ArrayList<Integer> alSelectedPositions;
public ContactsAdapter(Context context, ArrayList<String> alContactName, ArrayList<String> alContactEmail, ArrayList<String> alContactNumber, ArrayList<Boolean> alisFromLinkedIn) {
//Include one more variable for checking type i.e linked in or normal contact
super();
this.context = context;
this.alContactName = alContactName;
this.alContactEmail = alContactEmail;
this.alContactNumber = alContactNumber;
this.alFromLinkedIn = alisFromLinkedIn;
alSelectedPositions=new ArrayList<>();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_merge_contact, parent, false);
return new ContactsHolder(view);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
try {
((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
alSelectedPositions.add(position);
notifyDataSetChanged();
}
});
if(alSelectedPositions.get(position)==position){
((ContactsHolder) holder).imgMerge.setVisibility(View.VISIBLE);
}
else {
((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
check updated code. I have modified the #tahsinRupam code.
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
try {
((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(alSelectedPositions.size>0)
{
for(int i=0;i<a1SelectedPositions.size;i++)
{
//if you want to cleasr previous details of array
if(a1SelectedPositions.contains(position))
alSelectedPositions.remove(position);
else
alSelectedPositions.add(position);
}
}
else
{
alSelectedPositions.add(position);
notifyDataSetChanged();
}
});
//update the position on scroll
for(int i=0;i<a1SelectedPositions.size;i++)
{
if(alSelectedPositions.get(i)==position){
((ContactsHolder)holder).imgMerge.setVisibility(View.VISIBLE);
}
else {
((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Recently I had to implement a multi select RecyclerView, below I attached a simplified code snippet for a clean way to implement multi-select feature in RecyclerView:
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemHolder> implements IMultiSelectableList<Item> {
boolean selectionMode = false;
HashSet<Item> selectedItems;
ArrayList<Item> mItems;
public ItemAdapter(ArrayList<Item> Items) {
super();
selectedItems = new HashSet<>();
mItems = Items;
}
public void enterSelectionModeWithItem(int selectedItemPosition){
if(selectedItemPosition >= 0 && selectedItemPosition < mItems.size())
selectedItems.add(mItems.get(selectedItemPosition));
selectionMode = true;
notifyDataSetChanged();
}
public void clearSelectionMode() {
selectionMode = false;
selectedItems.clear();
notifyDataSetChanged();
}
public class ItemHolder extends RecyclerView.ViewHolder{
ImageView mImage;
public ItemHolder(View itemView) {
super(itemView);
mImage = itemView.findViewById(R.id.image);
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if(!selectionMode){
int selectedPosition = getAdapterPosition();
Item selectedItem = mItems.get(selectedPosition);
enterSelectionModeWithItem(selectedItem);
return true;
}
return false;
}
});
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int selectedPosition = getAdapterPosition();
Item selectedItem = mItems.get(selectedPosition);
//Capture Clicks in Selection Mode
if(selectionMode){
if(selectedItems.contains(selectedItem)){
selectedItems.remove(selectedItem);
mImage.setImageResource(R.drawable.ic_checkbox_blank_circle_outline_grey600_48dp);
} else {
selectedItems.add(selectedItem);
mImage.setImageResource(R.drawable.ic_checkbox_marked_circle_grey600_48dp);
}
}
}
});
}
public void setupView(Item item){
if(selectionMode){
if(selectedItems.contains(item)){
mImage.setImageResource(R.drawable.ic_checkbox_marked_circle_grey600_48dp);
} else {
mImage.setImageResource(R.drawable.ic_checkbox_blank_circle_outline_grey600_48dp);
}
}
}
#Override
public ItemAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_item, parent, false);
return new ItemHolder(view);
}
#Override
public void onBindViewHolder(ItemAdapter.ItemHolder holder, int position) {
holder.setupView(mItems.get(position));
}
#Override
public int getItemCount() {
return mItems != null ? mItems.size() : 0;
}
}
, I use an image to show selection like Gmail app but feel free to use whatever works for you (background color, font style, etc).
P.S: I designed a callback interface for a simple selection interactions, if it helps I can attach it too! Cheers!
You've to do some specific things:
Initialize an int type array (type can be different) and assign 0 value to all it's elements.
int[] selectedPos = null;
public ContactsAdapter(Context context, ArrayList<String> alContactName, ArrayList<String> alContactEmail, ArrayList<String> alContactNumber, ArrayList<Boolean> alisFromLinkedIn) {
//Include one more variable for checking type i.e linked in or normal contact
super();
this.context = context;
this.alContactName = alContactName;
this.alContactEmail = alContactEmail;
this.alContactNumber = alContactNumber;
this.alFromLinkedIn = alisFromLinkedIn;
alSelectedPositions=new ArrayList<>();
for(int i = 0 ; i < alContactName.size() ; i++)
selectedPos[i] = 0;
}
Store the selected positions in selectedPos.
Then, check if the position is selected and set visibility accordingly:
In onBindViewHolder() add the following code:
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
try {
((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selectedPos[position] = 1;
notifyDataSetChanged();
}
});
} catch (Exception e) {
e.printStackTrace();
}
// Checking if the position was selected
if(selectedPos[position] == 1)
((ContactsHolder) holder).imgMerge.setVisibility(View.VISIBLE);
else
((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
}
I have resolved my issue here is the code if it could help someone:
#Override
public ContactsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_merge_contact, parent, false);
final ContactsHolder holder = new ContactsHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (holder.getAdapterPosition() != RecyclerView.NO_POSITION) {
mSelectedItemPosition = holder.getAdapterPosition();
//notifyItemChanged(holder.getAdapterPosition());
notifyDataSetChanged();
}
}
});
return holder;
}
#Override
public void onBindViewHolder(ContactsHolder holder, int position) {
try {
if (mSelectedItemPosition == position) {
if (mergeFlag != 1) {
holder.imgMerge.setVisibility(View.VISIBLE);
mergeFlag = 1;
selectdParentId = contactsModels.get(position).alContactIdList;
} else{
//holder.relDone.setVisibility(View.GONE);
if (!selectdParentId.equals(contactsModels.get(position).alContactIdList)) {
holder.relDone.setVisibility(View.VISIBLE);
alChildId.add(contactsModels.get(position).alContactIdList);
} else {
holder.imgMerge.setVisibility(View.VISIBLE);
}
}
} else {
holder.imgMerge.setVisibility(View.GONE);
holder.relDone.setVisibility(View.GONE);
}
}

RecyclerView getting wrong position When Apply Search with Search Filter

I use RecyclerView and I have implemented Search Filter on it and i am facing a problem here
After I search when I press on item I get wrong position not one I searched it please help me to solve this problem
For example item number 2 name "Android" after search "android" the position go number one .. why get this problem ? .. thank you
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public List<RecyclerItem> listItems;
private Context mContext;
public MyAdapter(List<RecyclerItem> listItems, Context mContext) {
this.listItems = listItems;
this.mContext = mContext;
}
#Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final int position = holder.getAdapterPosition();
if (position == 0) {
Toast.makeText(mContext,"iOS",Toast.LENGTH_SHORT).show();
}
if (position == 1) {
Toast.makeText(mContext,"Android",Toast.LENGTH_SHORT).show();
}
}
});
return holder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final RecyclerItem itemList = listItems.get(position);
holder.txtTitle.setText(itemList.getTitle());
holder.txtDescription.setText(itemList.getDescription());
holder.txtOptionDigit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Display option menu
PopupMenu popupMenu = new PopupMenu(mContext, holder.txtOptionDigit);
popupMenu.inflate(R.menu.option_menu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.mnu_item_save:
Toast.makeText(mContext, "Saved " + listItems.get(position).getTitle(), Toast.LENGTH_SHORT).show();
break;
case R.id.mnu_item_delete:
//Delete item
Toast.makeText(mContext, "Deleted " + listItems.get(position).getTitle(), Toast.LENGTH_SHORT).show();
listItems.remove(position);
notifyDataSetChanged();
break;
default:
break;
}
return false;
}
});
popupMenu.show();
}
});
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private Button buttoncalling;
public TextView txtTitle;
public TextView txtDescription;
public TextView txtOptionDigit;
public ViewHolder(View itemView) {
super(itemView);
txtTitle = (TextView) itemView.findViewById(R.id.txtTitle);
txtDescription = (TextView) itemView.findViewById(R.id.txtDescription);
txtOptionDigit = (TextView) itemView.findViewById(R.id.txtOptionDigit);
buttoncalling = (Button) itemView.findViewById(R.id.bbbbbbbbbb);
buttoncalling.setOnClickListener(this);
}
#Override
public void onClick(View view) {
}
}
}
Filter
TextWatcher mTextWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().equals("")){
initAdapter();
} else {
searchItem(s.toString());
}
}
#Override
public void afterTextChanged(Editable s) {
}
};
private void initAdapter(){
adapter.listItems.clear();
for (int i = 0; i < 10; i++) {
listItems.add(new RecyclerItem("Item " + (i + 1), "Welcome to Torisan channel, this is description of item " + (i+1)));
}
adapter.notifyDataSetChanged();
}
private void searchItem(String itemname){
int resultCount = 0;
adapter.listItems.clear();
for (int i = 0; i < tempListItems.size(); i++){
if (tempListItems.get(i).getTitle().contains(itemname)){
listItems.add(new RecyclerItem("Item " + (i + 1), "Welcome to Torisan channel, this is description of item " + (i+1)));
resultCount ++;
}
}
if (resultCount == 0){
showToast();
}
adapter.notifyDataSetChanged();
}
public void showToast() {
// Set the toast and duration
int toastDurationInMilliSeconds = 1000;
mToastToShow = Toast.makeText(this, "No results found.", Toast.LENGTH_LONG);
// Set the countdown to display the toast
CountDownTimer toastCountDown;
toastCountDown = new CountDownTimer(toastDurationInMilliSeconds, 1000 /*Tick duration*/) {
public void onTick(long millisUntilFinished) {
mToastToShow.show();
}
public void onFinish() {
mToastToShow.cancel();
}
};
// Show the toast and starts the countdown
mToastToShow.show();
toastCountDown.start();
}
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public List<RecyclerItem> listItems;
private Context mContext;
public MyAdapter(List<RecyclerItem> listItems, Context mContext) {
this.listItems = listItems;
this.mContext = mContext;
}
#Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setTag(getAdapterPosition());
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final int position = Integer.parse(v.getTag().toString());
if (position == 0) {
Toast.makeText(mContext,"iOS",Toast.LENGTH_SHORT).show();
}
if (position == 1) {
Toast.makeText(mContext,"Android",Toast.LENGTH_SHORT).show();
}
}
});
return holder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final RecyclerItem itemList = listItems.get(position);
holder.txtTitle.setText(itemList.getTitle());
holder.txtDescription.setText(itemList.getDescription());
holder.txtOptionDigit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Display option menu
PopupMenu popupMenu = new PopupMenu(mContext, holder.txtOptionDigit);
popupMenu.inflate(R.menu.option_menu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.mnu_item_save:
Toast.makeText(mContext, "Saved " + listItems.get(position).getTitle(), Toast.LENGTH_SHORT).show();
break;
case R.id.mnu_item_delete:
//Delete item
Toast.makeText(mContext, "Deleted " + listItems.get(position).getTitle(), Toast.LENGTH_SHORT).show();
listItems.remove(position);
notifyDataSetChanged();
break;
default:
break;
}
return false;
}
});
popupMenu.show();
}
});
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private Button buttoncalling;
public TextView txtTitle;
public TextView txtDescription;
public TextView txtOptionDigit;
public ViewHolder(View itemView) {
super(itemView);
txtTitle = (TextView) itemView.findViewById(R.id.txtTitle);
txtDescription = (TextView) itemView.findViewById(R.id.txtDescription);
txtOptionDigit = (TextView) itemView.findViewById(R.id.txtOptionDigit);
buttoncalling = (Button) itemView.findViewById(R.id.bbbbbbbbbb);
buttoncalling.setOnClickListener(this);
}
#Override
public void onClick(View view) {
}
}
}
Please use this
for (int i = 0; i < tempListItems.size(); i++) {
if (listItems.get(getAdapterPosition()).getName().equals(tempListItems.get(i).getName())) {
int selectedPos = i; //SelectedPos is that index
break;
}
}

Categories

Resources