I need some help with Multi/Single selection. Found what I was looking for here, because of its simplicity.
I'm using a GridLayoutManager
I have over 90 items in my adapter, a CardView
with a TextView
and an ImageView
, while using the procedure described in the post.
When I select one, or more than one item, as I scroll down, other items "seems" to be selected because the background replicates, but they are not selected.
Tried placing the setOnClickListener
, in onBindViewHolder
and also in MyViewHolder class and in both of them I get the same behaviour. When scrolling down other items seems to be selected.
Used notifyItemChanged(position)
and notifyDataSetChanged()
in the adapter, but the background does not change at all, although the setSelected
works properly.
Also I used setHasFixedSize(true)
in the RecyclerView setup.
In onBindViewHolder
@Override
public void onBindViewHolder(MyViewHolder myViewHolder, final int position) {
PatternImages currentPattern = patternImages.get(position);
myViewHolder.setData(currentPattern, position);
myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.setSelected(!v.isSelected());
if (v.isSelected()) {
v.setBackgroundColor(ContextCompat.getColor(context, R.color.colorPrimaryHighLight));
} else {
v.setBackgroundColor(Color.WHITE);
}
notifyItemChanged(position);
}
});
}
Model
public class PatternImages {
private int imageId, imageName;
private boolean isSelected;
public PatternImages(int imageId, int imageName, boolean isSelected) {
this.imageId = imageId;
this.imageName = imageName;
this.isSelected = isSelected;
}
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public int getImageName() {
return imageName;
}
public void setImageName(int imageName) {
this.imageName = imageName;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
RecyclerView Setup
private void setUpPatternsRecyclerView() {
RecyclerView recyclerPatternsView = (RecyclerView) findViewById(R.id.pattern_image_recycler_view);
PatternImageAdapter adapter = new PatternImageAdapter(this, patternImages);
recyclerPatternsView.setAdapter(adapter);
ColumnQty columnQty = new ColumnQty(this, R.layout.item_image_pattern_cardview);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getApplicationContext(), columnQty.calculateNoOfColumns());
recyclerPatternsView.setHasFixedSize(true);
recyclerPatternsView.setLayoutManager(gridLayoutManager);
recyclerPatternsView.setItemAnimator(new DefaultItemAnimator());
recyclerPatternsView.addItemDecoration(new GridSpacing(columnQty.calculateSpacing()));
}
setData Method
public void setData(PatternImages currentPattern, int position) {
this.position = position;
patternName.setText(context.getString(currentPattern.getImageName()));
patternName.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/ElMessiri-SemiBold.ttf"));
patternImage.setBackgroundResource(currentPattern.getImageId());
if (position == 0 || position == 1) {
animationDrawable = (AnimationDrawable) patternImage.getBackground();
animationDrawable.start();
}
}
I tried @Kuffs solution and I'm posting my final code for reference.
onBindViewHolder
setData()
Methodrecently, i had worked on recyclerview multi selection, so you could try this first initialize sparseboolean, boolean an one int like this :
so on bindViewHolder, add this
then, implement onLongClickListener. on longClick add this:
after this, in onClick do this:
Try to keep the state in model but in view, and bind the model to view in
onBindViewHolder
.A
RecyclerView
as its name suggests, recycles views. That means that once a view scrolls off screen, it can be reused.Before a view is reused, it still contains all of the settings from the last time it was used. For example, if it contains a
TextView
, thatTextView
will still have its Text property set to whatever it was the last time it was displayed.The reason that some items "seem" to be selected is because your selected views that have scrolled off screen are now being reused and you have not unselected them.
In your
OnBindViewHolder
method, you need to "reset" all the views back to their defaults. In this case that would be to "turn off" whatever method you use to make a view appear selected.For example:
Essentially, every time you bind, you set the background colour to the selected or non selected state based on the relevant property in your model.