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