RecyclerView添加onItemClickListener更佳的解决方案

鸿洋 2016-05-12

本文由liaoinstan授权本公众号发布。

liaoinstan的博客地址:

http://blog.csdn.net/liaoinstan


对于RecyclerView添加onItemClickListener的监听,我之前为了方便直接在Adapter中进行处理,不过本文的方式的确更佳(当我看到ItemTouchHelper更加确信了这个观点,关于ItemTouchHelper文章也会尽快推送)。



自从RecyclerView发布以来,由于其高度的可交互性被广泛使用。但是RecyclerView确没有像ListView一样提供onItemClickListener却让人比较难过,网上搜索了一番有不少解决方案,但是其本质都是通过给每个item添加onClickListener来模仿一个伪onItemClickListener,这种为每个item添加点击监听的解决方案不用多想也知道是浪费性能的方法。能不能像ListView那样使用一个监听解决问题呢?


查阅RecyclerView的api发现虽然没有提供onItemClickListener但是提供了addOnItemTouchListener方法:

RecyclerView.addOnItemTouchListener(OnItemTouchListener listener)

既然可以添加触摸监听,那么我们完全可以获取触摸手势来识别点击事件,然后通过触摸坐标来判断点击的是哪一个item。


虽然听起来比较复杂,但是sdk 的 api已经为我们实现了大部分方法,我们只需要实现接口几行代码就可以搞定了。


下面先说一下使用方法,后面详细介绍其实现原理:


一、如何使用



其中OnRecyclerItemClickListener是自定义的一个触摸监听器,代码如下: 


仅有短短十多行代码,sdk已经为我们实现了大部分功能




GestureDetectorCompat中传入了一个ItemTouchHelperGestureListener


代码如下:



以上就是全部的代码了,看起来很少,其实包含的内容还是比较多的,下面详细剖析下其实现原理。


二、实现原理


查阅api发现,RecyclerView提供了设置触摸监听的方法,那么我们定义一个类OnRecyclerItemClickListener实现OnItemTouchListener


我们需要实现其3个方法:



其中第三个方法是处理触摸事件冲突的,跟我们没关系不用管它,前两个方法是不是很熟悉呢,这不就是View的事件分发机制里面的事件拦截和事件处理的两个方法吗?


参数里为我们提供了触摸事件的数据MotionEvent,我们要做的就是去解析坐标点和触摸规律来识别触摸手势,然后获取触摸的是哪一个item,再执行我们的回调,听起来很复杂,但是我前面已经说过了,sdk已经为我们实现了手势的识别


GestureDetectorCompat 就是处理手势的类:手势探测器,它比GestureDetector能更好兼容低版本的api,但使用方法是一致的,我们实例化一个手势探测器:



我们实例化手势探测器的时候需要提供一个手势监听器:OnGestureListener,探测器识别出手势后就会回调手势监听器中对应的方法,我们就可以在回调方法中做我们想做的事情了。


sdk为我们提供了两个手势监听器:

OnGestureListenerOnDoubleTapListener


(1)、OnGestureListener

回调接口如下:



(2)、OnDoubleTapListener

回调接口如下:



可以看出OnGestureListener主要回调各种单击事件,而OnDoubleTapListener回调各种双击事件。而我们需要处理的点击事件其实就是上面的:

onSingleTapUp()

值得一提的是sdk 还提供了一个外部类SimpleOnGestureListener,这个类实现了上面两个接口的所有方法,但全都是空实现,函数体里什么也没写,其中就是把上面两个接口合并一下,给出默认的空实现,这样继承SimpleOnGestureListener的时候就不用实现每一个方法了,既然如此,那么我们定义一个类去继承它吧。


定义一个ItemTouchHelperGestureListener 继承自SimpleOnGestureListener ,实现onSingleTapUp方法:




到这里,已经获取到了RecyclerView的点击事件和触摸事件数据MotionEvent ,那么我们怎么知道点击的是哪一个item呢?


RecyclerView已经为我们提供了这样的方法:


findChildViewUnder()


我们可以通过这个方法获得点击的item,同时我们调用RecyclerView的另一个方法getChildViewHolder(),可以获得该item的ViewHolder,最后再回调我们定义的虚方法onItemClick()就ok了,这样我们就可以在外部实现该方法来获得item的点击事件了:




这样我们就从如何实现和实现原理两部分对RecyclerView添加onItemClickListener的方案进行了描述。文章中涉及到的手势检测类,如果你还没用了解过,那么一定要去了解一下,会极大的方便你去检测一些手势。



--欢迎长按或者扫码关注--

-本公众号支持投稿,直接投递md文件至我邮箱-


本站仅按申请收录文章,版权归原作者所有
如若侵权,请联系本站删除
觉得不错,分享给更多人看到
鸿洋 热门文章:

Android 第一行代码赠书 [全球限量版]    阅读/点赞 : 9481/392

冰冻三尺非一日之寒-自学篇    阅读/点赞 : 7510/248

Android一些你需要知道的布局优化技巧    阅读/点赞 : 7366/175

冰冻三尺非一日之寒-博客篇    阅读/点赞 : 6871/302

Android程序员的专属情人节    阅读/点赞 : 6565/197

2016的文章都在这里,2017年加油~    阅读/点赞 : 6238/173

2016一路有你,2017一起同行    阅读/点赞 : 4601/212