2015-04-05 46 views
3

我一直試圖在幾天內使用新的RecyclerView小部件,並認爲我設法創建了Horizo​​ntal和Grid佈局,並且還克服了以下事實:它缺乏實現OnClickListener的直接方式(我使用GreenRobot's EventBus),但我仍然很難在整個回收過程中選擇一個項目並保留該狀態(樣式)。RecyclerView - 當未調用onBindViewHolder時,findViewHolderForPosition總是返回null

這是我在上面顯示的代碼中使用了我的適配器現在

public class ArticuloItemAdapter extends RecyclerView.Adapter<ArticuloItemAdapter.ItemHolder> { 
    private ArrayList<ArticuloObject> mItems; 
    private LayoutInflater mLayoutInflater; 
    private int mSize; 
    private int mSelectedPosition; 
    private RecyclerView mRecyclerView; 

    public ArticuloItemAdapter(Context context, RecyclerView rv, ArrayList<ArticuloObject> articulos) { 

     mLayoutInflater = LayoutInflater.from(context); 
     mItems=articulos ;  
     mSize = context.getResources() 
       .getDimensionPixelSize(R.dimen.icon); 
     mSelectedPosition = -1; 
     mRecyclerView = rv; 
    } 

    @Override 
    public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View itemView = mLayoutInflater.inflate(R.layout.gallery_recycler_row, parent, false); 
     return new ItemHolder(itemView, this); 
    } 

    @Override 
    public void onBindViewHolder(ItemHolder holder, int position) {  
     Ion.with(holder.getPicImageView()) 
       .placeholder(R.drawable.owner_placeholder) 
       .resize(mSize, mSize) 
       .centerCrop() 
       .error(R.drawable.owner_error) 
       .load(mItems.get(position).getUrl()); 

     //Update the views as they got recycled 
     if (mSelectedPosition != position) { 
      holder.getPicImageView().setBackgroundColor(Color.TRANSPARENT); 
     } else { 
      holder.getPicImageView().setBackgroundColor(Color.CYAN); 
     } 
    } 

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

    public int getSelectedPosition() { 
     return mSelectedPosition; 
    } 

    public void setSelectedPosition(int mSelectedPosition) { 
     this.mSelectedPosition = mSelectedPosition; 
    } 

    public RecyclerView getRecyclerView() { 
     return mRecyclerView; 
    } 

    /* Required implementation of ViewHolder to wrap item view */ 
    public class ItemHolder extends RecyclerView.ViewHolder implements 
      View.OnClickListener { 
     private ArticuloItemAdapter mParent; 
     private ImageView mPicImageView; 

     public ItemHolder(View itemView, ArticuloItemAdapter parent) { 
      super(itemView); 
      itemView.setOnClickListener(this); 

      mParent = parent; 

      mPicImageView = (ImageView) itemView.findViewById(R.id.picture_image_view); 
     } 

     public ImageView getPicImageView() { 
      return mPicImageView; 
     } 

     @Override 
     public void onClick(View v) { 
      EventBus.getDefault().post(new OnArticuloCartaClickEvent(this, getPosition())); 
      setItemActivated(v); 
     } 

     public void setItemActivated(View v) { 

      //Check position of previous selected item. The first time an item is selected, the previous position will be -1 
      if (mParent.getSelectedPosition() >= 0) { 
       ItemHolder row = (ItemHolder) mParent.getRecyclerView().findViewHolderForPosition(mParent.getSelectedPosition()); 
       if (row != null) { 
        row.getPicImageView().setBackgroundColor(Color.TRANSPARENT); 
       } 
      } 
      mParent.setSelectedPosition(getPosition()); 
      v.findViewById(R.id.picture_image_view).setBackgroundColor(Color.CYAN); 

     } 
    } 

} 

的代碼,我做的跟蹤所選項目如下:

一,在onclick(視圖v)事件:

  1. 每當用戶單擊一個項目,我稱之爲setItemActivated方法
  2. 在setItemActivated方法中,我檢查selectedPosition是否大於或等於0(當沒有選中項目時默認值爲-1)。
  3. 如果以前的狀態是真的,我試圖讓在該位置ViewHolder,如果該視圖不爲空,我改變ImageView回到它的背景色的原始背景色(透明)
  4. 設置新值mSelectedPosition的使用getPosition()
  5. 最後當前位置,ImageView的當前ViewHolder內部背景顏色改變爲不同的顏色(在此情況下CYAN)

II。在onBindViewHolder(ItemHolder保持器,INT位置)方法:

如果選擇的項目(mSelectedPosition)的位置是從 不同正在顯示的視圖的位置,我改變ImageView的背景 顏色回到其默認顏色。 否則,我將ImageView的顏色更改爲用於標識所選項目(CYAN)的顏色。

只要RecyclerView有相當數量的項目需要開始回收視圖,所有這些工作。但是,如果它不如我的情況,我已經注意到,findViewHolderForPosition總是返回null,因此,我不能將之前選擇的項目的顏色更改回其默認顏色,所以我最終得到了超過選擇一個項目。

enter image description here

而且更糟糕的是,作爲RecyclerView沒有回收的話,就是onBindViewHolder方法永遠不會調用,因此我無法對碼數內調整項目的顏色因此。

請,我真的很感激,如果有人能告訴我我在做什麼錯在這裏,或者給出一些想法。無法做出像選擇項目一樣基本的東西真的讓人沮喪。

在此先感謝。

回答

4

發生這種情況的原因是,當選定的項目發生更改時,您並不是告訴RecyclerView先前的項目已失效。

,而不是試圖手動設置,請執行下列操作:

public void setItemActivated(View v) { 
    final int myPos = getAdapterPosition(); 
    if (myPos == RecyclerView.NO_POSITION) { 
     // very rare case where item is clicked but its adapter position 
     // is unknown. ignore the event. 
     // See docs of getAdapterPosition for details 
    } 
    final int prevSelected = mParent.getSelectedPosition(); 
    mParent.setSelectedPosition(myPos); 
    if (prevSelected >= 0 && prevSelected < mParent.getItemCount()) { 
     mParent.notifyItemChanged(prevSelected); 
    } 
    mParent.notifyItemChanged(myPos); 
} 

RecyclerView將調用onBind爲應該更新視圖。您無需關心之前選擇的項目在哪裏。

+0

謝謝@yigit。你能告訴我在哪裏可以找到這個'getAdapterPosition'方法嗎?我試圖在我的適配器或'ViewHolder'中的任何地方使用它,但該方法無法識別?從文檔看,它看起來像'getPosition()',但我不明白爲什麼我不能使用它。 – eddy 2015-04-05 18:28:32

+0

我想你沒有最新版本的支持庫。 https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#getAdapterPosition() – yigit 2015-04-05 20:59:34

+0

但我用'compile'c​​om.android.support:appcompat-v7:21.0。 3''和'compile'c​​om.android.support:recyclerview-v7:21.0.3''。我甚至使用「+」通配符來獲取最新版本,但我仍然無法使用'getAdapterPosition' – eddy 2015-04-05 21:05:10