2017-12-27 461 views
1

我的ViewHolder實現了View.OnClickListener,正如this answer中的建議。除此之外,我再次檢查了我的適配器類與官方文檔中的示例類似。爲什麼我的RecyclerView.ViewHolder的onClick方法有時不被調用?

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 

    private View view; 

    public ViewHolder(View view) { 
     super(view); 
     view.setOnClickListener(this); 
     this.view = view; 
    } 

    public View getView() { 
     return view; 
    } 

    @Override 
    public void onClick(View view) { 
     Context context = view.getContext(); 
     Intent intent = new Intent(context, DetailsActivity.class); 
     context.startActivity(intent); 
    } 
} 

但如果我測試我的應用程序我觀察這個非常奇怪的現象:如果我攻上排在啓動過程中看到,如預期執行onClick方法。現在我向下滾動,使其他行可見。我點擊某處並沒有任何反應,第二次點擊 - 如果它在同一行上 - 再次運行。如果我滾動回到頂部,則會發生同樣的情況,我必須點擊兩次以獲取我的onClick方法。

任何想法爲什麼會發生這種情況?

編輯:的完整代碼,現在設置聽者onBindViewHolder

public class ComposersAdapter extends RecyclerView.Adapter<ComposersAdapter.ViewHolder> { 

    public static class ViewHolder extends RecyclerView.ViewHolder { 

     private View view; 

     public ViewHolder(View view) { 
      super(view); 
      this.view = view; 
     } 

     public View getView() { 
      return view; 
     } 
    } 

    private final String EXTRA_COMPOSER_ID = "composerId"; 
    private List<Composer> composers; 

    public ComposersAdapter(List<Composer> composers) { 
     this.composers = composers; 
    } 

    @Override 
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_layout, parent, false); 
     return new ViewHolder(view); 
    } 

    @Override 
    public void onBindViewHolder(final ViewHolder holder, int position) { 
     View view = holder.getView(); 
     TextView textView = view.findViewById(R.id.textView); 
     textView.setText(composers.get(position).getTitle()); 
     holder.getView().setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       Context context = view.getContext(); 
       Intent intent = new Intent(context, ComposerActivity.class); 
       intent.putExtra(EXTRA_COMPOSER_ID, holder.getAdapterPosition()); 
       context.startActivity(intent); 
      } 
     }); 
    } 

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

UPDATE:這個問題似乎被連接到RecyclerView駐留在我設置app:layout_scrollFlags="scroll|enterAlways"活動的工具欄。如果我刪除該問題不存在了。也許這與工具欄捕捉觸摸事件有關?我沒有足夠的經驗來檢查我自己。

+0

爲什麼不在onBindViewHolder中完成它?而不是在這裏有一個點擊監聽器,試試在綁定方法的根視圖上有一個 – Kushan

+0

你是對的,這是更清潔。但問題依然存在。 –

+0

對不起,我剛剛看到了Kushan的評論。 @Elias,請提供適配器的完整代碼,我想你可能會錯誤地持有/分配視圖引用。 – rgv

回答

1

指定 onBindViewHolder(RecyclerView.ViewHolder holder, int position)中的點擊收聽者。

onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
holder.itemView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
        // start some activity 
      } 
}); 
} 

在綁定視圖持有者是何時一個視圖持有者正確地綁定到適配器和視圖的個別實例可在這裏。

holder.itemView 

將給你對viewHolder的視圖實例的引用。 因此,您不需要在ViewHolder中使用getView()類似的方法。

+1

'holder.setOnClickListener'如何工作?從持有者處獲得視圖後,您可能是指'view.setOnClickListener',或者我誤解了某些東西? –

+0

是的,你是正確的@伊利亞斯!我在腦海裏打字,對不起!我剛剛更新了答案。 – rgv

+0

好吧,我更新了我的代碼,但問題仍然存在。無論如何謝謝澄清! –

0

ViewHolder介紹有關其內的RecyclerView地方的項目視圖和元數據。

RecyclerView.Adapter實現應該子類ViewHolder和添加字段用於高速緩存可能昂貴findViewById(int)的結果。

我在項目中有類似的問題,我做了一些示例,你可以看看可能有助於解決你的問題。

public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ViewHolder> { 

    private List<Ad> adsList= new ArrayList<>(); 
    private Context mContext; 
    static OnItemClickListener mItemClickListener; 
    //Provide a reference to the views for each data item 
    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 

     @BindView(R.id.mainHolder) 
     public RelativeLayout placeHolder; 

     @BindView(R.id.tv_ad_name) 
     public TextView tvAdName; 

     @BindView(R.id.tv_no_of_rating) 
     public TextView tvNoOfRating; 

     @BindView(R.id.tv_minOs) 
     public TextView tvMinOs; 

     @BindView(R.id.iv_product_thumbnail) 
     public ImageView ivPrductThumbnail; 


     public ViewHolder(View v) { 
      super(v); 
      ButterKnife.bind(this, v); 
      placeHolder.setOnClickListener(this); 
     } 
     @Override 
     public void onClick(View v) { 
      if (mItemClickListener != null) { 
       mItemClickListener.onItemClick(itemView, getPosition()); 
      } 
     } 

    } 

    public interface OnItemClickListener { 
     void onItemClick(View view, int position); 
    } 

    public void setOnItemClickListener(final OnItemClickListener mItemClickListener) { 
     this.mItemClickListener = mItemClickListener; 
    } 

    //Provide a suitable constructor 
    public ProductAdapter(Context context){ 
     mContext = context; 
    } 
    public void setAd(List<Ad> aList) { 
     adsList.clear(); 
     adsList.addAll(aList); 
     notifyDataSetChanged(); 
    } 
    //Create new views (invoked by the layout manager) 
    @Override 
    public ProductAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 

     //Creating a new view 
     View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_list_items,parent,false); 

     ViewHolder vh = new ViewHolder(v); 
     return vh; 
    } 

    //Replace the contents of a view (invoked by the layout manager 
    @Override 
    public void onBindViewHolder(ProductAdapter.ViewHolder holder, int position) { 

     // - replace the contents of the view with that element 

     Ad ad = adsList.get(position); 
     holder.tvAdName.setText(ad.getProductName()); 
     holder.tvNoOfRating.setText(ad.getNumberOfRatings()); 
     holder.tvMinOs.setText(ad.getMinOSVersion()); 

     Glide.with(mContext) 
       .load(ad.getProductThumbnail()) 
       .into(holder.ivPrductThumbnail); 
    } 

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

完整可行的代碼鏈接here。和link2

編輯:你可能已在申報ViewHolder類中的TextView

+0

不幸的是,這也沒有幫助。緩存視圖不應該是必需的,因爲設置文本按預期工作,並將實際的點擊監聽器放置在其他地方(如btw,你應該提到它在MainActivity.java中)不會改變任何內容。我有這種感覺,我在這裏錯過了一些基本的東西。 –

+0

你可以請檢查這個:https://github.com/dharmakshetri/Android-API-Demos/blob/master/app/src/main/java/co/apidemos/adapter/GitHubAdapter.java –

+0

我不知道這會工作與否,但是你可以請嘗試通過從這裏刪除'靜態'公共靜態類ViewHolder擴展RecyclerView.ViewHolder {}。 –

相關問題