有人使用RecyclerView找到了一种方法来设置一个onClickListener的项目在RecyclerView? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我确信有一种方法让RecyclerView监听onClick事件,但我不能完全弄清楚。


当前回答

这里有一个策略,它给出了一个类似于ListView实现的结果,因为你可以在活动或片段级别而不是适配器或ViewHolder级别定义侦听器。它还定义了一些抽象类,这些抽象类负责适配器和持有者的大量样板工作。

抽象类

首先,定义一个抽象Holder,它扩展了RecyclerView。并定义了一个泛型数据类型T,用于将数据绑定到视图。bindViews方法将由一个子类实现,用于将数据映射到视图。

public abstract class Holder<T> extends RecyclerView.ViewHolder {
    T data;

    public Holder(View itemView) {
        super(itemView);
    }

    public void bindData(T data){
        this.data = data;
        bindViews(data);
    }

    abstract protected void bindViews(T data);
}

同样,创建一个抽象适配器,扩展RecyclerView.Adapter<Holder<T>>。这定义了3个接口方法中的2个,子类将需要实现最后一个onViewHolderCreated方法。

public abstract class Adapter<T> extends RecyclerView.Adapter<Holder<T>> {
    List<T> list = new ArrayList<>();

    @Override
    public void onBindViewHolder(Holder<T> holder, int position) {
        holder.bindData(list.get(position));
    }

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

    public T getItem(int adapterPosition){
        return list.get(adapterPosition);
    }
}

具体类

现在创建一个扩展Holder的新具体类。该方法只需定义视图并处理绑定。这里我使用ButterKnife库,但请随意使用itemView.findViewById(…)方法代替。

public class PersonHolder extends Holder<Person>{
    @Bind(R.id.firstname) TextView firstname;
    @Bind(R.id.lastname) TextView lastname;

    public PersonHolder(View view){
        super(view);
        ButterKnife.bind(this, view);
    }

    @Override
    protected void bindViews(Person person) {
        firstname.setText(person.firstname);
        lastname.setText(person.lastname);
    }
}

最后,在持有RecyclerView的Activity或Fragment类中,你会有这样的代码:

// Create adapter, this happens in parent Activity or Fragment of RecyclerView
adapter = new Adapter<Person>(){
    @Override
    public PersonHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.layout_person_view, parent, false);

        PersonHolder holder = new PersonHolder(v);
        v.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                int itemPos = holder.getAdapterPosition();
                Person person = getItem(itemPos);

                // do something with person
                EventBus.getDefault().postSticky(new PersonClickedEvent(itemPos, person));
            }
        });

        return holder;
    }
};

其他回答

这里有一个更好的和不那么紧密耦合的方式来实现一个OnClickListener的RecyclerView。

用法片段:

RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
    new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
      @Override public void onItemClick(View view, int position) {
        // do whatever
      }

      @Override public void onLongItemClick(View view, int position) {
        // do whatever
      }
    })
);

RecyclerItemClickListener实现:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;


public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
  private OnItemClickListener mListener;

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

    public void onLongItemClick(View view, int position);
  }

  GestureDetector mGestureDetector;

  public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
    mListener = listener;
    mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            if (child != null && mListener != null) {
                mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
            }
        }
    });
}

  @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
    View childView = view.findChildViewUnder(e.getX(), e.getY());
    if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
      mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
      return true;
    }
    return false;
  }

  @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }

  @Override
  public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
}

这对我来说很管用。将OnClickListener附加到onBindView。我真的不知道这是否会影响性能,但它似乎用很少的代码就能很好地工作。

public void onBindViewHolder(ViewHolder holder, final int position) {
    holder.view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "Recycle Click" + position, Toast.LENGTH_SHORT).show();
            }
    });
}

这是我的自定义适配器的完整代码,这段代码将用XML文件“list_item”中定义的列表项膨胀行,它还将在具有各自位置的所有列表项行上执行单击事件。

public class MyCustomAdapter extends RecyclerView.Adapter`<`AdapterMyCustomAdapter.ViewHolder> {

    public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
        public onItemClickListener mListener;
        public ViewHolder(View v, onItemClickListener listener) {
            super(v);
            mListener =listener;
            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            mListener.onRecyclerItemClick(v, getPosition());
        }

        public static interface onItemClickListener {
            public void onRecyclerItemClick(View view , int position);
        }
    }

    @Override
    public int getItemCount() {
        return 5;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int pos) {      

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);

    /* here list_item is an xml file we want to inflate ...it is same as we do in case of listview for customization.*/

        MyCustomAdapter.ViewHolder vh = new ViewHolder(v, new MyCustomAdapter.ViewHolder.onItemClickListener() {

            @Override
            public void onRecyclerItemClick(View view, int position) {
                System.out.println("clicked on list item at position " +position);
            } 
        });
        return vh;
    }
}

RecyclerView没有OnClickListener,必须自己实现它。

我喜欢在适配器中添加OnItemClickListener接口,当您从ViewHolder中单击项目视图时调用onClick方法。因此,管理项目点击的职责不在ViewHolder和Adapter的范围内。将决定做什么的活动或片段

为监听器和监听器对象添加接口。

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

  ...

  private static OnItemClickListener onItemClickListener;

  ...

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

  ...
}

我们捕获项目根视图的单击,以及当回调触发时适配器上的onClick侦听器调用。

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

  ...

  private static OnItemClickListener onItemClickListener;

  ...

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

  ...

  public static class ViewHolder extends RecyclerView.ViewHolder {
      public ImageView imageView;

      public ViewHolder(View itemRootView) {
          super(itemRootView);
          imageView = (ImageView) itemRootView.findViewById(R.id.itemImage);

          itemRootView.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View view) {
                  int position  = ViewHolder.super.getAdapterPosition();
                  onItemClickListener.onItemClick(view,position);
              }
          });
      }
  }
}

由于活动或片段,片段在我们的情况下,我们分配一个监听器到适配器和onClick回调,我们将获得选定的项目的位置和打开一个详细的活动项目。

public class ItemsFragment extends Fragment {
    ...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       ...    
        ((ItemsAdapter) adapter).setOnItemClickListener(new ItemsAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                //Do something when an item has been clicked
            }
        });
        ...
    }
...
}

这就是我最后需要的东西,以防有人发现它有用:

public static class ViewHolder extends RecyclerView.ViewHolder {

    public ViewHolder(View item) {

        super(item);
        item.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("RecyclerView", "onClick:" + getAdapterPosition());
            }
        });

    }
}

来源:http://blog.csdn.net/jwzhangjie/article/details/36868515