OnTouchListerner shall not interpret swipes do open DrawerLayout as Long Click

Multi tool use
up vote
2
down vote
favorite
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())
}
}
}

This question has an open bounty worth +50
reputation from the_dani ending in 6 days.
The question is widely applicable to a large audience. A detailed canonical answer is required to address all the concerns.
add a comment |
up vote
2
down vote
favorite
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())
}
}
}

This question has an open bounty worth +50
reputation from the_dani ending in 6 days.
The question is widely applicable to a large audience. A detailed canonical answer is required to address all the concerns.
You can avoid calling super in long press to notify system about you've already consumed long press.
– Jeel Vankhede
Nov 10 at 14:46
@JeelVankhede This method has no return type. The problem is that I do not want gestureDetector to detect a LongPress if I'm swiping to open the drawer...
– the_dani
Nov 10 at 14:48
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
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())
}
}
}

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())
}
}
}


edited Nov 10 at 14:49
asked Nov 9 at 21:53
the_dani
6211721
6211721
This question has an open bounty worth +50
reputation from the_dani ending in 6 days.
The question is widely applicable to a large audience. A detailed canonical answer is required to address all the concerns.
This question has an open bounty worth +50
reputation from the_dani ending in 6 days.
The question is widely applicable to a large audience. A detailed canonical answer is required to address all the concerns.
You can avoid calling super in long press to notify system about you've already consumed long press.
– Jeel Vankhede
Nov 10 at 14:46
@JeelVankhede This method has no return type. The problem is that I do not want gestureDetector to detect a LongPress if I'm swiping to open the drawer...
– the_dani
Nov 10 at 14:48
add a comment |
You can avoid calling super in long press to notify system about you've already consumed long press.
– Jeel Vankhede
Nov 10 at 14:46
@JeelVankhede This method has no return type. The problem is that I do not want gestureDetector to detect a LongPress if I'm swiping to open the drawer...
– the_dani
Nov 10 at 14:48
You can avoid calling super in long press to notify system about you've already consumed long press.
– Jeel Vankhede
Nov 10 at 14:46
You can avoid calling super in long press to notify system about you've already consumed long press.
– Jeel Vankhede
Nov 10 at 14:46
@JeelVankhede This method has no return type. The problem is that I do not want gestureDetector to detect a LongPress if I'm swiping to open the drawer...
– the_dani
Nov 10 at 14:48
@JeelVankhede This method has no return type. The problem is that I do not want gestureDetector to detect a LongPress if I'm swiping to open the drawer...
– the_dani
Nov 10 at 14:48
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
accepted
I solved it the following way:
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
}
})
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
I solved it the following way:
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
}
})
add a comment |
up vote
0
down vote
accepted
I solved it the following way:
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
}
})
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
I solved it the following way:
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
}
})
I solved it the following way:
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
}
})
answered 11 hours ago
the_dani
6211721
6211721
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53233700%2fontouchlisterner-shall-not-interpret-swipes-do-open-drawerlayout-as-long-click%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
7YUfeBf,PXJcIwT36cTvMLJs0p7TndrmviO4OlRA5DuODNN4 ViGYIXZdw,4POBR1mpomWUOJ7Je TC7kVG0wQ
You can avoid calling super in long press to notify system about you've already consumed long press.
– Jeel Vankhede
Nov 10 at 14:46
@JeelVankhede This method has no return type. The problem is that I do not want gestureDetector to detect a LongPress if I'm swiping to open the drawer...
– the_dani
Nov 10 at 14:48