I'm detecting clicks in my recyclerview using the OnItemTouchListener class below. Unfortunately, this does not work well when using a DrawerLayout. If I swipe to open the DrawerLayout/NavigationView, my OnItemTouchListener gets this event too and executes the onLongClick action.
This does not happen if I use the ViewHolders' View.OnLongClick. What's the little secret, Views' OnLongClickListener checks before firing an LongClick-event to detect that the drag-action is not a long click, but a gesture to open the drawer?
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())
}
}
}