android - OnTouchListerner 不应将打开 DrawerLayout 的滑动解释为长按

标签 android android-recyclerview kotlin android-view navigation-drawer

我正在使用下面的 OnItemTouchListener 类检测我的 recyclerview 中的点击。不幸的是,这在使用 DrawerLayout 时效果不佳。如果我滑动打开 DrawerLayout/NavigationView,我的 OnItemTouchListener 也会收到此事件并执行 onLongClick 操作。

如果我使用 ViewHolders 的 View.OnLongClick,则不会发生这种情况。有什么小 secret ,Views 的 OnLongClickListener 在触发 LongClick 事件之前进行检查以检测拖动操作不是长按,而是打开抽屉的手势?

class OnItemTouchListener(context: Context, recyclerView: RecyclerView, private var onTouchCallback: ItemTouchListener) : RecyclerView.OnItemTouchListener {

    //region Variables

    private val gestureDetector: GestureDetector

    //endregion

    init {
        gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
            override fun onSingleTapUp(e: MotionEvent?): Boolean {
                return true
            }

            override fun onLongPress(e: MotionEvent?) {
                val child: View? = recyclerView.findChildViewUnder(e!!.x, e.y)

                if (child != null) {
                    onTouchCallback.onItemLongClick(child, recyclerView.getChildLayoutPosition(child), e)
                }

                super.onLongPress(e)
            }
        })
    }

    //region TouchHandler

    override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
        val child = rv.findChildViewUnder(e.x, e.y)

        if (child != null && gestureDetector.onTouchEvent(e)) {
            onTouchCallback.onItemClick(child, rv.getChildLayoutPosition(child), e)
        }

        return false
    }

    override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {

    }

    override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {

    }

    //endregion

    interface ItemTouchListener {
        fun onItemClick(view: View, pos: Int, e: MotionEvent)
        fun onItemLongClick(view: View, pos: Int, e: MotionEvent)
    }

    companion object {
        fun isViewClicked(container: View, @IdRes viewId: Int, e: MotionEvent): Boolean {
            val view = container.findViewById<View>(viewId)

            val rect = Rect()
            view.getGlobalVisibleRect(rect)

            return view.isVisible && rect.contains(e.rawX.toInt(), e.rawY.toInt())
        }
    }
}

最佳答案

我是这样解决的:

gestureDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() {
    private val MIN_SWIPE_DISTANCE: Int = 50
    private lateinit var downMotionEvent: MotionEvent

    override fun onDown(e: MotionEvent?): Boolean {
        e?.let { downMotionEvent = it }

        return super.onDown(e)
    }

    override fun onSingleTapUp(e: MotionEvent?): Boolean {
        return true
    }

    override fun onLongPress(e: MotionEvent?) {
        e?.let {
            val child: View? = recyclerView.findChildViewUnder(it.x, it.y)

            if (child != null && !isGestureSwipe(it)) {
                onTouchCallback.onItemLongClick(child, recyclerView.getChildLayoutPosition(child), it)
            }
        }

        super.onLongPress(e)
    }

    fun isGestureSwipe(e: MotionEvent): Boolean {
        return downMotionEvent.x - e.x <= MIN_SWIPE_DISTANCE
    }
})

关于android - OnTouchListerner 不应将打开 DrawerLayout 的滑动解释为长按,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53233700/

相关文章:

java - 如何在 RecyclerView 中设置负边距装饰?或者为什么这是不可能的?

android - Recycler Adapter 中的 BindView 和 UnbindVIew

java - 如何修复仅显示单行的android的回收 View View 问题

Kotlin - "run"用于静态 Java 方法

java - 当返回 1xx 状态代码时,Spring Boot 请求卡在那里

java - 使用套接字在 Java 中的客户端服务器应用程序上进行 xml 处理

android - 在虚拟盒中运行的 android 假 gps

android - 更新到支持库 23.2.0 后,前 Lollipop 设备中的后退箭头和溢出图标颜色错误

Android 以编程方式设置 ListView 背景与透明度问题

kotlin - viewBindingenabled true 和 buildfeatures viewBinding true 有什么区别