Android中解决RecyclerView各种点击事件的方法

完美解决RecyclerView点击事件、长按事件、子项点击事件

自从Google推出了RecyclerView之后,便可以完全取代ListView,个人感觉唯一的美中不足是对于itemView的各种点击事件不够完美。观点只代表个人看法。应最近项目需求实现itemView的子项点击事件,便写篇博客记录一下,若是能够帮到你,我深感荣幸。接下来,便对RecyclerView进行简单的封装,使得它更方便实现各种点击事件。

我们都知道,对与RecyclerView的使用,是创建一个adapter类,然后在adapter类中再创建一个ViewHolder的内部类。我们要做的,正是对这两个类进行封装,让其实现itemView点击事件、长按事件、子项点击事件。

首先,我的处理方式是,对于开发者来说,只需要对adapter进行setxxx()方法的调用,例如设置itemView的点击事件:adapter.setOnRecyclerViewItemClickListener(...);对该方法传入自定义的接口即可。也就是说,我们需要自定义一个adapter类。那我们就先创建一个类,命名为BaseRecylerAdapter,此后,我们也应当创建一个BaseViewHolder类,接下来开始搞事情。

BaseRecylerAdapter类

public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder>
  implements View.OnClickListener
  ,View.OnLongClickListener {

 private OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
 private OnRecyclerViewItemLongClickListener onRecyclerViewItemLongClickListener;
 private OnSubViewClickListener onSubViewClickListener;

 @Override
 public void onBindViewHolder(BaseViewHolder holder, int position) {
  holder.itemView.setTag(position);
  holder.onBind(position);
  if (onRecyclerViewItemClickListener != null) {
   holder.itemView.setOnClickListener(this);
  }
  if (onRecyclerViewItemLongClickListener != null) {
   holder.itemView.setOnClickListener(this);
  }
  if (onSubViewClickListener != null) {
   holder.setSubViewClickListener(onSubViewClickListener,position);
  }
 }

 public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener onRecyclerViewItemClickListener) {
  this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener;
 }

 public void setOnRecyclerViewItemLongClickListener(OnRecyclerViewItemLongClickListener onRecyclerViewItemLongClickListener) {
  this.onRecyclerViewItemLongClickListener = onRecyclerViewItemLongClickListener;
 }

 public void setOnSubViewClickListener(OnSubViewClickListener listener){
  this.onSubViewClickListener = listener;
 }

 @Override
 public void onClick(View v) {
  if (v.getTag() != null) {
   int position = (int) v.getTag();
   onRecyclerViewItemClickListener.onItemClick(position);
  }
 }

 @Override
 public boolean onLongClick(View v) {
  if (v.getTag() != null){
   int position = (int)v.getTag();
   onRecyclerViewItemLongClickListener.onItemLongClick(position);
  }
  return true;
 }

 public interface OnRecyclerViewItemClickListener {
  void onItemClick(int position);
 }

 public interface OnSubViewClickListener{
  void onSubViewClick(View v, int position);
 }

 public interface OnRecyclerViewItemLongClickListener {
  void onItemLongClick(int position);
 }

}

可以看到我们在类中创建了三个接口类

public interface OnRecyclerViewItemClickListener {
  void onItemClick(int position);
 }

 public interface OnSubViewClickListener{
  void onSubViewClick(View v, int position);
 }

 public interface OnRecyclerViewItemLongClickListener {
  void onItemLongClick(int position);
 }

这三个接口便是用于点击事件的回调,看名字就能分别出各自的功能。itemView的点击回调public interface OnRecyclerViewItemClickListener,itemView的长按public interface OnRecyclerViewItemLongClickListener,子项View的点击回调public interface OnSubViewClickListener。都是点击事件的处理,没有点击发送怎么行呢,对吧!所以,这个类还实现了View.OnClickListener View.OnLongClickListener 这两个接口,本别实现itemView的点击事件和长按事件。

可以看到,BaseRecyclerAdapter继承自RecyclerView.Adapter<BaseViewHolder>,此时我们只需要实现onBindViewHolder 这个方法即可。来分析这个方法。

@Override
 public void onBindViewHolder(BaseViewHolder holder, int position) {
  holder.itemView.setTag(position);
  holder.onBind(position);
  if (onRecyclerViewItemClickListener != null) {
   holder.itemView.setOnClickListener(this);
  }
  if (onRecyclerViewItemLongClickListener != null) {
   holder.itemView.setOnClickListener(this);
  }
  if (onSubViewClickListener != null) {
   holder.setSubViewClickListener(onSubViewClickListener,position);
  }
 }

可以看出 这个方法里都是操作我们自定义的BaseViewHolder类。接下来就是三个空判断,也就是说,我们若是没有设置相应的点击事件,就不会初始化对应的点击事件,这样的处理方式还是很常见的。处理这个点击事件最麻烦的就是position的问题,因此我们使用的技巧是,对View对象设置tag的方式。查看源码便知道,View有个方法 setTag(Object obj); 我们就可以将对应的position赋值给这个tag,我们使用View的getTag() 方法就可以得到对应点击View的position了。在BaseRecylerAdapter类实现的点击接口和长按接口就可以知道这样的操作,类容如下。

 @Override
 public void onClick(View v) {
  if (v.getTag() != null) {
   int position = (int) v.getTag();
   onRecyclerViewItemClickListener.onItemClick(position);
  }
 }

 @Override
 public boolean onLongClick(View v) {
  if (v.getTag() != null){
   int position = (int)v.getTag();
   onRecyclerViewItemLongClickListener.onItemLongClick(position);
  }
  return true;
 }

BaseViewHolder类

public abstract class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
 private BaseRecyclerAdapter.OnSubViewClickListener onSubViewClickListener;
 public BaseViewHolder(View itemView) {
  super(itemView);
  findViewById(itemView);
 }

 /**
  * 传入子项点击事件所需参数
  * @param listener 自定义的接口
  * @param tagPosition tag
  */
 public void setSubViewClickListener(BaseRecyclerAdapter.OnSubViewClickListener listener, int tagPosition){
  this.onSubViewClickListener = listener;
  initSubViewClick(tagPosition);
 }

 /**
  * 通过id匹配控件(开发者自行实现)
  * @param itemView 父布局
  */
 abstract protected void findViewById(View itemView);

 /**
  * 用于装载数据(开发者自行实现)
  * @param position 当前位置
  */
 abstract protected void onBind(int position);

 /**
  * 初始化子项的点击事件(为子项设置tag)
  * @param tagPosition tag
  */
 protected void initSubViewClick(int tagPosition){

 }

 /**
  * 实现子项点击事件的转发
  * @param v
  */
 @Override
 public void onClick(View v) {
  if (v.getTag() != null) {
   int position = (int) v.getTag();
   onSubViewClickListener.onSubViewClick(v,position);
  }
 }
}

这是个抽象类,也就是说,在使用的时候需要实现其中的抽象方法。为了逻辑清晰,我在这里写了两个抽象方法

/**
  * 通过id匹配控件(开发者自行实现)
  * @param itemView 父布局
  */
 abstract protected void findViewById(View itemView);

 /**
  * 用于装载数据(开发者自行实现)
  * @param position 当前位置
  */
 abstract protected void onBind(int position);

看注释也就很清楚这两个方法的作用是什么,这里就不多说了。

到此,我们已经实现了itemView的点击和长按事件,接下来我们来实现对itemView子项的点击事件。

在BaseViewHolder类中,也实现了一个View的点击事件接口。子项的点击方式和itemView的点击事件是一样的套路,使用tag。接下来我们来看个例子,就明白了。

public class RecyclerAdapterMyActivity extends BaseRecyclerAdapter{
 private List<MyActivityBean> list;
 public RecyclerAdapterMyActivity(List<MyActivityBean>list){
  this.list = list;
 }

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

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

 public class ViewHolder extends BaseViewHolder {
  private TextView tv_name,tv_title,tv_content;
  private Button activityBtnChat;
  private Button activityBtnCancel;
  ViewHolder(View itemView) {
   super(itemView);
  }

  @Override
  protected void findViewById(View itemView) {
   tv_name = itemView.findViewById(R.id.tv_my_activity_name);
   tv_title = itemView.findViewById(R.id.tv_my_activity_title);
   tv_content = itemView.findViewById(R.id.tv_my_activity_content);
   activityBtnChat = itemView.findViewById(R.id.activity_btn_chat);
   activityBtnCancel = itemView.findViewById(R.id.activity_btn_cancel);

  }

  @Override
  protected void onBind(int position) {
   MyActivityBean bean = list.get(position);
   tv_name.setText(bean.getName());
   tv_title.setText(bean.getTitle());
   tv_content.setText(bean.getContent());
  }

  @Override
  protected void initSubViewClick(int tagPosition) {
   activityBtnChat.setTag(tagPosition);
   activityBtnCancel.setTag(tagPosition);
   activityBtnChat.setOnClickListener(this);
   activityBtnCancel.setOnClickListener(this);
  }
 }
}

这段代码是最近项目中的一小段代码。其中,adapter类继承BaseRecyclerAdapter,viewHolder类继承BaseViewHolder。尤其要注意的是ViewHolder的构造方法中一定要有super(itemView); 其余的方法都会按照正确的逻辑执行。若要实现itemView的子项点击事件,需要重写父类的initSubViewClick(int tagPosition) ; 方法。其中参数tagPosition便是对应的itemVIew处于RecyclerView中的位置。在这里是为两个button添加点击事件,先为其设置tag,再设置点击事件,我们这里的setOnClickListener(this) ;  参数传的是this,是因为,我们再父类中实现了View的onClick(View v); 方法。

这样,我们便完成了各类点击事件。

使用方法也很简单,就是直接操作你的adapter就可以了,调用adapter.setXxxx(...) 即可方便地实现各种点击事件。当然,要是你地需求是Touchu事件,或子项地长按事件等,都可以通过这样类似地方式来实现。

最后

方法不止一种,这样地操作方式,这只是我的一种思考。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android使用RecyclerView实现自定义列表、点击事件以及下拉刷新

    Android使用RecyclerView 1. 什么是RecyclerView RecyclerView 是 Android-support-v7-21 版本中新增的一个 Widgets,官方对于它的介绍则是:RecyclerView 是 ListView 的升级版本,更加先进和灵活. 简单来说就是:RecyclerView是一种新的视图组,目标是为任何基于适配器的视图提供相似的渲染方式.它被作为ListView和GridView控件的继承者,在最新的support-V7版本中提供支持. 2.

  • Android中RecyclerView点击Item设置事件

    在上一篇Android RecylerView入门教程中提到,RecyclerView不再负责Item视图的布局及显示,所以RecyclerView也没有为Item开放OnItemClick等点击事件,这就需要开发者自己实现.博客最下面有Demo程序运行动画. 奉上Demo的Github链接. 在调研过程中,发现有同学修改RecyclerView源码来实现Item的点击监听,但认为这不是一个优雅的解决方案,最终决定在RecyclerView.ViewHolder上做文章. 思路是:因为ViewH

  • Android XRecyclerView最简单的item点击事件处理

    以前一直都是用PullToRefresh,后来觉得还是太out了.现在很多人都是用RecyclerView,很简单的用法,布局多样化,主要是有瀑布流.这才知道RecyclerView.LayoutManager真正的强大. 但是说要addHeaderView这个的话,RecyclerView没有实现,所以我用了XRecyclerView,其实它也是在RecyclerView的基础上再次封装的,用起来还是蛮好的. 这里说一下,正确的使用XRecyclerView点击item做事件处理的问题.其实就

  • RecyclerView实现水波纹点击效果

    本文实例为大家分享了RecyclerView实现水波纹点击效果的具体代码,供大家参考,具体内容如下 效果图 item.xml 这里就是主要设置background为我们后面写的一个selector <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" andro

  • Android RecyclerView点击事件

    一.概述 随着Android L版本的发布,RecyclerView已经逐渐地取代了ListView,用来显示较多的数据集,RecyclerView相比ListView在性能上有了大幅度的提升,可以说RecyclerView是AbsListView的升级版本.RecyclerView自带了ViewHolder使用,与ListView缓存convertView不同的是,RecyclerView缓存的是ViewHolder,操作对象也是ViewHolder.虽然ListView也带有缓存conver

  • Android RecyclerView实现点击条目删除

    本文实例为大家分享了RecyclerView实现点击条目删除的具体代码,供大家参考,具体内容如下 MainActivity.java public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button mButton1; private Button mButton2; private Button mButton3; private Button mButton4

  • Android RecyclerView的Item点击事件实现整理

    自从开始使用RecyclerView代替ListView,会发现有很多地方需要学习.前一段时间的学习记录有: RecyclerView的滚动事件研究 - DevWiki RecyclerView的ViewHolder和Adapter的封装优化 - DevWiki RecyclerView问题记录 - DevWiki 实现 RecyclerView的Item的点击事件有三种方式: 在创建 ItemView时添加点击监听 当 ItemView attach RecyclerView时实现 通过Rec

  • Recyclerview添加头布局和尾布局、item点击事件详解

    简介: 本篇博客主要包括recyclerview添加多种布局以及添加头布局和尾布局,还有item点击事件 思路: 主要重写Recyclerview.Adapter中的一些方法 1.public int getItemCount()  item熟练  +2(头布局和尾布局) 2.public int getItemViewType(int position)   判断position 设置itemType 3.创建不同的ViewHolder,分别用来加载头布局,正常布局,尾布局 4.public

  • Android中解决RecyclerView各种点击事件的方法

    完美解决RecyclerView点击事件.长按事件.子项点击事件 自从Google推出了RecyclerView之后,便可以完全取代ListView,个人感觉唯一的美中不足是对于itemView的各种点击事件不够完美.观点只代表个人看法.应最近项目需求实现itemView的子项点击事件,便写篇博客记录一下,若是能够帮到你,我深感荣幸.接下来,便对RecyclerView进行简单的封装,使得它更方便实现各种点击事件. 我们都知道,对与RecyclerView的使用,是创建一个adapter类,然后

  • Android中捕捉menu按键点击事件的方法

    本文实例讲述了Android中捕捉menu按键点击事件的方法.分享给大家供大家参考.具体如下: @Override public boolean onCreateOptionsMenu(Menu menu) { /* * add()方法的四个参数,依次是: 1.组别,如果不分组的话就写Menu.NONE, * 2.Id,这个很重要,Android根据这个Id来确定不同的菜单 3.顺序,那个菜单现在在前面由这个参数的大小决定 * 4.文本,菜单的显示文本 */ menu.add(Menu.NONE

  • Android开发使用RecyclerView添加点击事件实例详解

    目录 引言 一.RecyclerView基本使用 1. 添加适配器Adapter 2. 创建列表的每个项的item_layout.xml文件 3. 在activity中使用 二.RecyclerView点击事件详细步骤 1. 在RecyclerView对应的Adapter类里面新建接口 2. 在Adapter类里创建setOnItemClickListener方法 3. 在Adapter类的onBindViewHolder里给每个item设置回调 4. 在RecyclerView对应的Activ

  • JS检测页面中哪个HTML标签触发点击事件的方法

    本文实例讲述了JS检测页面中哪个HTML标签触发点击事件的方法.分享给大家供大家参考,具体如下: 在html标签中,为了页面显示的美观,会在标签中相互嵌套,在做"效果"的时候就难免不了的添加各种事件,例如: <a href=""><span onclick="">dddd</span></a> 当用户点击的时候,想确定是链接产生的事件还是span标签onclick标签产生的事件,这个有时候是很有必要

  • Android 中ListView的Item点击事件失效的快速解决方法

    在平常的开发过程中,我们的ListView可能不只是简单的显示下文本或者按钮,更多的是显示复杂的布局,这样的话,我们就得自己写布局和自定义adapter了,一般是继承于BaseAdapter,示例代码见下方.写ListView的点击事件时OnItemClickListener,onItemClick方法没有执行,导致ListView中Item条目点击事件失效,而Item中的View点击事件可以在getView方法中进行处理.导致整个Item点击失效的原因多半是由于在[你自己定义的Item中存在诸

  • Angularjs中使用指令绑定点击事件的方法

    项目中,模板中的菜单是jQuery控制的,在Angularjs中就运行不到了,因为菜单项是ng-repeat之后的. 如html <ul id="main-menu"> <li class=""> <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external n

  • Android中ListView的item点击没有反应的解决方法

    如果stu_item.xml里面包括button或者checkbox等控件,默认情况下list的item会失去焦点,导致无法响应item的事件,最常用的解决办法是在stu_item.xml的布局文件中设置descendantFocusability属性. 该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系. 属性的值有三种: beforeDescendants:viewgroup会优先其子类控件而获取到焦点 afterDescendants:viewgroup只有

  • Android recycleView的应用和点击事件实例详解

    Android recycleView的应用和点击事件 效果图: 长按是删除: 下面代码: MainActivity 类 public class MainActivity extends AppCompatActivity { RecyclerView rv; List<String> mList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.on

  • Android中解决页签手指按下从左到右滑动的bug

    有一种方法可以阻止父层的View截获touch事件,就是调用 getParent().requestDisallowInterceptTouchEvent(true);方法. 一旦底层View收到touch的 action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也无法截获以后的action 在ViewPagerIndicator项目中找到TabPageIndicator该类,添加如下代码 @Override public boolean dispa

  • Android 中使用RecyclerView实现底部翻页

    RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好.接下来通过一系列的文章讲解如何使用RecyclerView,彻底抛弃ListView. 最近在做pad端的app,需要一个像网页一样效果,之前使用addView方式,页码少的时候还可以,能实现效果,但是碰到了一个1000多页的界面,就GG了,页码半天显示不出来,于是使用RecyclerView作为容器,主要是看中RecyclerView的复用,不说了,看代

随机推荐