2017-12-27 11 views
1

私のViewHolderthis answerに示唆されているようにView.OnClickListenerを実装しています。それ以外は私のアダプタークラスは公式文書の例に似ていることを二重にチェックしました。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メソッドが実行されます。今度は、他の行を見えるようにスクロールします。どこかでタップしても何も起こらず、2番目のタップ(同じ行にあるかどうか)が再び動作します。上にスクロールすると同じことが起こり、onClickというメソッドを呼び出すために2回タップする必要があります。

これは何が起こっているのですか?

EDIT:完全なコード、今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

申し訳ありません私は九州のコメントを見ました。 @エライアス、アダプタの完全なコードを提供してください、私はあなたが保持している/ビューの参照を間違って割り当てていると思う。 – rgv

答えて

1

クリックリスナーを onBindViewHolder(RecyclerView.ViewHolder holder, int position)に割り当てます。

バインドビューホルダーは、ビューホルダーがアダプターに正しくバインドされており、ビューの個々のインスタンスがここで使用可能な場合です。

holder.itemView 

は、viewHolderのビューインスタンスへの参照を提供します。 その結果、ViewHolderのメソッドに似ていません。getView()

+1

'holder.setOnClickListener'はどのように機能しますか?所有者からビューを取得した後でおそらく 'view.setOnClickListener'を意味するか、何かを誤解していますか? –

+0

はい、あなたは正しい@Eliasです!私は私の心の入力、申し訳ありませんでした!私はちょうど答えを更新しました。 – rgv

+0

私のコードは更新されましたが、問題はそのまま残ります。とにかく明確化のためにありがとう! –

0

ViewHolderRecyclerView内のその場所に関するアイテムビューおよびメタデータを記述する。

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

私はこの意志を知らないあなたはここから 'static'を削除してみてください。public static class ViewHolder extends RecyclerView.ViewHolder {}。 –

関連する問題