获取绑定recyclerView的ItemTouchHelper私有变量mItemTouchHelperGestureListener,并获取ItemTouchHelperGestureListener的长按方法onLongPress,自定义item的onTouch方法在点击时调用onLongPress。
val mItemTouchHelper = ItemTouchHelper(mCallback)
mItemTouchHelper.attachToRecyclerView(rv)
try {
val c = mItemTouchHelper::class.java
val field = c.getDeclaredField("mItemTouchHelperGestureListener")
field.isAccessible = true
val listener = field.get(mItemTouchHelper)
val listenerClass =
Class.forName("androidx.recyclerview.widget.ItemTouchHelper$ItemTouchHelperGestureListener")
val onLongPressMethod =
listenerClass.getDeclaredMethod("onLongPress", MotionEvent::class.java)
setLongClickDelay(Handler(), rv, 500, listener, onLongPressMethod)
} catch (e: Exception) {
e.printStackTrace()
}
private fun setLongClickDelay(
handler: Handler, v: RecyclerView, delay: Long, listener: Any, method: Method
) {
val delayMillis = if (delay < 50) 50 else delay
v.addonItemTouchListener(object : onItemTouchListener {
private val TOUCH_MAX = 50
var mEvent: MotionEvent? = null
private var mLastMotionX = 0
private var mLastMotionY = 0
private var mHasPerformedLongPress = false
private val performLongClick = Runnable {
// mHasPerformedLongPress = v.performLongClick();
if (mEvent != null) {
mHasPerformedLongPress = true
//响应长按onLongPress
method.invoke(listener, mEvent)
mEvent = null
}
}
override fun onInterceptTouchEvent(rv: RecyclerView, event: MotionEvent): Boolean {
val x = event.x.toInt()
val y = event.y.toInt()
when (event.action) {
MotionEvent.ACTION_UP -> {
mEvent = null
handler.removeCallbacks(performLongClick)
// case 1
v.tag = mHasPerformedLongPress
if (!mHasPerformedLongPress) {
v.performClick()
} else {
// 长按消耗了,此事件
return true
}
}
MotionEvent.ACTION_MOVE -> if (Math.abs(mLastMotionX - x) > TOUCH_MAX || Math.abs(
mLastMotionY - y
) > TOUCH_MAX
) {
mEvent = null
handler.removeCallbacks(performLongClick)
}
MotionEvent.ACTION_DOWN -> {
mHasPerformedLongPress = false
handler.removeCallbacks(performLongClick)
mLastMotionX = x
mLastMotionY = y
// 不能直接用mEvent = event,这样赋值 mEvent 的 getX 和 getY 得到的值是相对屏幕(或者是父布局)的,
// 具体原理不清楚
mEvent = MotionEvent.obtain(event)
handler.postDelayed(performLongClick, delayMillis)
}
MotionEvent.ACTION_CANCEL -> handler.removeCallbacks(performLongClick)
}
return false
}
override fun onTouchEvent(rv: RecyclerView, event: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
}