recyclerView通过反射和onTouchListener更改item的长按响应时间

  获取绑定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) {}
    })
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值