RecyclerView 添加点击事件的几种方法
来源:互联网 发布:mac 穿越火线下载安装 编辑:程序博客网 时间:2024/05/17 23:35
相较于ListView,RecyclerView没有提供诸如setOnItemClickListener()方法,便捷的为每个子项添加点击事件,所以我们需要费一些功夫,手动去处理这些。
第一种方法:ViewHolder
首先是第一种方法,利用ViewHolder,直接上代码:
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ViewHolder> { // ... public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView tvName; public TextView tvHometown; private Context context; public ViewHolder(Context context, View itemView) { super(itemView); this.tvName = (TextView) itemView.findViewById(R.id.tvName); this.tvHometown = (TextView) itemView.findViewById(R.id.tvHometown); this.context = context; // 向每一个子项的view绑定ClickListener itemView.setOnClickListener(this); } // 处理点击事件 @Override public void onClick(View view) { int position = getLayoutPosition(); // gets item position User user = users.get(position); //通过view来获取数据 Toast.makeText(context, tvName.getText(), Toast.LENGTH_SHORT).show(); } }}
代码很直观,只需要在生成ViewHolder时,向子项的每个view绑定ClickListener,然后重写点击方法即可,同时如果我们可以在OnClick方法中去调用自定义不同接口的回调方法,来实现不同的需求。代码如下:
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ViewHolder> { // ... // 定义回调的listener private static OnItemClickListener listener; // 定义接口 public interface OnItemClickListener { void onItemClick(View itemView, int position); } // 此处用来绑定listener,根据需求的不同,传入不同的listener public void setOnItemClickListener(OnItemClickListener listener) { this.listener = listener; } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView tvName; public TextView tvHometown; public ViewHolder(final View itemView) { super(itemView); this.tvName = (TextView) itemView.findViewById(R.id.tvName); this.tvHometown = (TextView) itemView.findViewById(R.id.tvHometown); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Triggers click upwards to the adapter on click if (listener != null) listener.onItemClick(itemView, getLayoutPosition()); } }); } }}
其实和之前的代码相差不大,就是在OnClick方法中去调用了接口的方法,而这个接口方法是外部传入的,所以可以实现不同的功能,创建adapter代码如下:
ContactsAdapter adapter = ...;adapter.setOnItemClickListener(new ContactsAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { String name = users.get(position).name; Toast.makeText(UserListActivity.this, name + " was clicked!", Toast.LENGTH_SHORT).show(); }});
第二种方法:利用包装类
下面这种方法是来自Getting your clicks on RecyclerView,首先看使用方法:
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() { @Override public void onItemClicked(RecyclerView recyclerView, int position, View v) { // 此处添加点击事件 }});
接下来是包装类ItemClickSupport的实现:
public class ItemClickSupport { private final RecyclerView mRecyclerView; private OnItemClickListener mOnItemClickListener; private OnItemLongClickListener mOnItemLongClickListener; private View.OnClickListener mOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (mOnItemClickListener != null) { RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v); } } }; private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (mOnItemLongClickListener != null) { RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v); } return false; } }; private RecyclerView.OnChildAttachStateChangeListener mAttachListener = new RecyclerView.OnChildAttachStateChangeListener() { @Override public void onChildViewAttachedToWindow(View view) { if (mOnItemClickListener != null) { view.setOnClickListener(mOnClickListener); } if (mOnItemLongClickListener != null) { view.setOnLongClickListener(mOnLongClickListener); } } @Override public void onChildViewDetachedFromWindow(View view) { } }; private ItemClickSupport(RecyclerView recyclerView) { mRecyclerView = recyclerView; mRecyclerView.setTag(R.id.item_click_support, this); mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener); } public static ItemClickSupport addTo(RecyclerView view) { ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); if (support == null) { support = new ItemClickSupport(view); } return support; } public static ItemClickSupport removeFrom(RecyclerView view) { ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); if (support != null) { support.detach(view); } return support; } public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) { mOnItemClickListener = listener; return this; } public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) { mOnItemLongClickListener = listener; return this; } private void detach(RecyclerView view) { view.removeOnChildAttachStateChangeListener(mAttachListener); view.setTag(R.id.item_click_support, null); } public interface OnItemClickListener { void onItemClicked(RecyclerView recyclerView, int position, View v); } public interface OnItemLongClickListener { boolean onItemLongClicked(RecyclerView recyclerView, int position, View v); }}
通过源码实现可以看到这个包装类可以实现OnClick和OnLongClick两个方法,并且不需要像第一种方法一样在Adapter类中添加点击事件和传入回调接口,只需要在Activity或者Fragment中用一行简单的代码代替即可,大大增加了代码的可读性,并且使得代码更加易于维护,操作起来也更加简单。
我们跟着这个包装类的使用方法来看看原理:
首先是调用ItemClickSupport的静态方法addTo,并传入一个RecyclerView的实例,首先会判断该实例是否已经绑定了ItemClickSupport,此处我们以第一次绑定为例,此时ItemClickSupport为空,则会自动生成一个新的ItemClickSupport,调用其构造方法。
private ItemClickSupport(RecyclerView recyclerView) { mRecyclerView = recyclerView; mRecyclerView.setTag(R.id.item_click_support, this); mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);}
前面两行容易理解,主要是第三行,addOnChildAttachStateChangeListener(mAttachListener),首先介绍一下OnChildAttachStateChangeListener方法:
/** * A Listener interface that can be attached to a RecylcerView to get notified * whenever a ViewHolder is attached to or detached from RecyclerView. */ public interface OnChildAttachStateChangeListener { /** * Called when a view is attached to the RecyclerView. * * @param view The View which is attached to the RecyclerView */ public void onChildViewAttachedToWindow(View view); /** * Called when a view is detached from RecyclerView. * * @param view The View which is being detached from the RecyclerView */ public void onChildViewDetachedFromWindow(View view); }
源码中的介绍是,当我们滑动RecyclerView时,会有新的view附着和旧的view离开,这个方法的核心就在于此,我们在onChildViewAttachedToWindow(View view)方法中,向新生成的view去绑定监听器:
public void onChildViewAttachedToWindow(View view) { if (mOnItemClickListener != null) { view.setOnClickListener(mOnClickListener); } if (mOnItemLongClickListener != null) { view.setOnLongClickListener(mOnLongClickListener); }}
可以看到,我们在这一步向新附着的View添加了mOnClickListener或者mOnLongClickListener,而这两个监听器是取决于我们在Activity或者Fragment传入的回调接口,回调接口可以按照项目需要进行自定义的处理。
至此,该包装类的使用方法和原理就介绍完毕。相较于第一种方法,可以发现第二种方法更加的简洁并且耦合性低,在实际项目中应该采取第二种方法较为合适。
- RecyclerView 添加点击事件的几种方法
- 给recyclerview的item添加点击事件的 一种方法
- 为RecyclerView的Item添加点击及长按事件的三种方法
- RecyclerView添加点击事件
- RecyclerView添加点击事件
- Recyclerview添加点击事件
- 为RecyclerView添加item的点击事件
- 为RecyclerView添加item的点击事件
- 为RecyclerView添加item的点击事件
- 为RecyclerView添加item的点击事件
- 为RecyclerView添加item的点击事件
- RecyclerView中点击事件的添加
- 为RecyclerView添加item的点击事件
- 为RecyclerView添加item的点击事件
- 给RecyclerView的Item添加点击事件
- RecyclerView添加Item的点击事件
- 为RecyclerView添加item的点击事件
- 对RecyclerView的item添加点击事件
- linux下java读取文件名乱码
- MAVEN项目文件目录
- HDOJ 5720 Wool
- win7驱动器中没有磁盘
- 观察者模式-猫捉老鼠(委托与事件)
- RecyclerView 添加点击事件的几种方法
- 死锁的定义、产生原因、必要条件、避免死锁和解除死锁的方法
- Hibernate总结(三)--之一级缓存
- HDU(1715)大菲波数
- pool(四)——EvictionTimer
- POJ 1978 Hanafuda Shuffle
- 监听ContentProvider数据改变
- AndroidStudio默认继承V7包下的AppCompatActivity
- jQuery——遍历