首页 > 学院 > 开发设计 > 正文

ItemTouchHelper实现短按拖拽

2019-11-06 09:50:05
字体:
来源:转载
供稿:网友

前言

ItemTouchHelper是一个RecyclerView的工具类,目的是为简化RecyclerView拖拽、侧滑功能的开发工作。网络搜索可以找到其具体用法。因为ItemTouchHelper默认是长按之后才能拖拽RecyclerView中的item,并且不能通过配置改变这种情况,所以我这里跟大家分享一下实现短按item拖拽的方式。

分析源码

RecyclerView版本:24.0.0

ItemTouchHelper的用法一般如下:

ItemTouchHelper helper = new ItemTouchHelper(new Callback());helper.attachToRecyclerView(rv);

其attachToRecyclerView方法实现如下,其中我们要关注的点是对setupCallbacks方法的调用。

public void attachToRecyclerView(@Nullable RecyclerView recyclerView) { ... setupCallbacks(); ...}

setupCallbacks方法实现如下,其中调用了initGestureDetector方法,看来ItemTouchHelper是通过GestureDetector来实现拖拽功能的。

PRivate void setupCallbacks() { ... initGestureDetector();}

initGestureDetector实现如下,确实是通过GestureDetector实现的,我们来看看ItemTouchHelperGestureListener中对事件的处理。

private void initGestureDetector() { if (mGestureDetector != null) { return; } mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(), new ItemTouchHelperGestureListener());}

ItemTouchHelperGestureListener 实现如下,直接在onLongPress方法中去处理拖拽事件。

private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDown(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { ... } }

一路看来可以判断出,我们无法通过代码设置来实现短按拖拽,只能通过非寻常方法来实现了。

实现方法

其实最简单的一种方法就是直接把ItemTouchHelper类复制一份,将OnLongPress中的代码复制到OnShowPress方法中去就可以实现了,但是这样做会造成代码的冗余,违背了程序设计的避免重复原则,所以我此处不采用此方法。

另一种方法就是采用反射去改变长按短按的时间,不过这两个值是在GestureDetector中的,而且是常量,无法修改,所以只能略过了。

第三种方法是将ItemTouchHelper中的GestureDetector的监听器给取出来,然后设置一个自定义的监听器进去,在自定义的监听器的短按事件onShowPress中去调用原监听器的长按方法onLongPress。我的实现代码如下,其中mDoDrag变量是为不让整个itemView都能拖拽 而加进去的,如果不需要可以删去:

public class ListenerInterceptor { private GestureDetector.OnGestureListener mListener2BeIntercept; private InterceptListener mListener2Intercept; private boolean mDoDrag = true; public ListenerInterceptor(ItemTouchHelper helper) { mListener2Intercept = new InterceptListener(); try { Field fGesDetector = ItemTouchHelper.class.getDeclaredField("mGestureDetector"); fGesDetector.setaccessible(true); Object objGesDetector = fGesDetector.get(helper); Field fImpl = GestureDetectorCompat.class.getDeclaredField("mImpl"); fImpl.setAccessible(true); Object objImpl = fImpl.get(objGesDetector); Field fLis = null; try { fLis = objImpl.getClass().getDeclaredField("mListener"); }catch (Exception e){e.printStackTrace();} Object oDet = null; if (fLis == null){ Field fDet = objImpl.getClass().getDeclaredField("mDetector"); fDet.setAccessible(true); oDet = fDet.get(objImpl); fLis = oDet.getClass().getDeclaredField("mListener"); } fLis.setAccessible(true); mListener2BeIntercept = (GestureDetector.OnGestureListener) fLis.get(oDet); fLis.set(oDet, mListener2Intercept); } catch (Exception e) { e.printStackTrace(); } } public void setDoDrag(boolean drag){ mDoDrag = drag; } public class InterceptListener extends GestureDetector.SimpleOnGestureListener { @Override public void onShowPress(MotionEvent e) { if (mDoDrag) mListener2BeIntercept.onLongPress(e); } }}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表