1

我需要多选/单选帮助。找到我正在寻找的here,因为它的简单性。 我使用的是GridLayoutManager我在适配器中有90多个项目,CardView使用TextViewImageView,同时使用the post中描述的过程。在Android中实现多选选项RecyclerView

当我向下滚动时选择一个或多个项目时,其他项目“似乎”被选中,因为后台复制,但未选中。 试图把setOnClickListener,在onBindViewHolder,也在MyViewHolder类,并在他们两个我得到相同的行为。当向下滚动其他项目似乎被选中。 在适配器中使用了notifyItemChanged(position)notifyDataSetChanged(),但背景完全没有改变,但setSelected正常工作。 另外我在RecyclerView设置中使用了setHasFixedSize(true)

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); 
     } 
    }); 
} 

模型

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设置

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方法

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(); 
    } 


} 
+0

把代码第一 –

+0

@阿维纳什·罗伊,完成 – Racu

回答

1

顾名思义,RecyclerView,回收意见。这意味着,一旦视图滚动屏幕,它可以被重用。

在重用视图之前,视图仍包含上次使用视图的所有设置。例如,如果它包含TextView,那么TextView仍将其Text属性设置为最后一次显示时的内容。

某些项目“看起来”被选中的原因是因为您所选择的已经滚屏的视图现在正在被重用并且您没有取消选择它们。

在您的OnBindViewHolder方法中,您需要将所有视图重置为默认值。在这种情况下,可以“关闭”您用来制作视图的任何方法。

例如:

@Override 
public void onBindViewHolder(MyViewHolder myViewHolder, final int position) { 

    final PatternImages currentPattern = patternImages.get(position); 

    myViewHolder.setData(currentPattern, position); 
    myViewHolder.itemView.setBackgroundColor(currentPattern.isSelected() ?R.color.Red: R.color.WHITE); // choose your colors 

    myViewHolder.itemView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      currentPattern.setSelected(!currentPattern.isSelected()) 
      notifyItemChanged(position); 
     } 
    }); 
} 

从本质上讲,每绑定一次,您将针对您的模型中相应属性的背景色选择或不选择的状态。

+0

发布的代码已经,谢谢。 – Racu

+0

我在文章中添加了我的'setData'方法,并且包含了您在代码中提供的第5行。 我可能错了,但是在'onClick'中提供的代码中,我的模式不会改变背景,我相信(我是菜鸟)。 现在感谢您的意见,请注意,它可以使用或不使用'notifyItemChanged(position)'。 为了我的理解,我的错误并不是为视图初始提供背景,因为视图的背景已经是白色(尝试使用'Color.RED'和'Color.BLUE'进行测试) – Racu

+1

是的,上面的代码会改变背景。那是NotifyItemChanged所做的。它导致OnBindViewHolder再次被调用相关的位置,然后依次设置容器视图的背景颜色。 – Kuffs

2

最近,我有recyclerview多选择的工作,所以你可以先试试这个初始化sparseboolean布尔的一个INT这样的:

private SparseBooleanArray storeChecked = new SparseBooleanArray(); 
private boolean isMultiselect; 
private int itemSelected; 

等bindViewHolder,添加此

holder.view.setbackground(storechecked.get(position) ? Color.White : Color.Black) 

然后, 实现onLongClickListener。 上longClick 补充一点:在此之后

if(!ismultiSelect){ 
    storechecked.put(getAdapterPosition(), true); 
    notifyDataSetChanged(getAdapterPosition()); 
    triggerOnLongClickListener(++itemSelected); // using listerner i've transfer position to fragment for actionmode selected count 

} 


,在的onClick做到这一点:

if(ismultiSelect){ 
    boolean tof = storechecked.get(getAdapterPosition()); 
      if (tof){ 
       triggerOnItemClickListener(--itemSelected, v); // transfer position to update unselected 
       storeChecked.delete(position);// delete position of unselected position in the fragment 
      }else { 
       triggerOnItemClickListener(++itemSelected, v); 
      // transfer position to update selected position in the fragment 
     } 
    } 

**Other methods in adapter** 

    //clear on actionmode close 
    public void exitMultiselectMode() { 
    isMultiselect = false; 
    itemSelected = 0; 
    storeChecked.clear(); 
    notifyDataSetChanged(); 
} 

    // get all selected position 
    public List<Integer> getSelectedItems() { 
    List<Integer> items = new ArrayList<>(storeChecked.size()); 
    for (int i = 0; i < storeChecked.size(); ++i) { 
     items.add(storeChecked.keyAt(i)); 
    } 
    return items; 
    } 
+0

这比更好的答案比原来 –

+1

@VygintasB我已更新的代码和一些修复将有助于在recyclerview中获得工作多选,让我知道如果有任何其他问题面临:) ps:以前我在一些因为一些在计算器上输入应用程序代码和解释失踪。 –

1

尽量保持状态模式,但考虑到,并绑定模型查看在onBindViewHolder

0

我试过@Kuffs解决方案,并发布我的最终代码以供参考。

onBindViewHolder

@Override 
public void onBindViewHolder(final MyViewHolder myViewHolder, final int position) { 

    final PatternImages currentPattern = patternImages.get(position); 
    myViewHolder.setData(currentPattern, position); 
    myViewHolder.itemView.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      currentPattern.setSelected(!currentPattern.isSelected()); 

      notifyItemChanged(position); 
     } 
    }); 

} 

setData()方法

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(); 
    } 
    itemView.setBackgroundColor(currentPattern.isSelected() ? ContextCompat.getColor(context, R.color.colorPrimaryHighLight) : Color.WHITE); 
}