OnTouchListerner shall not interpret swipes do open DrawerLayout as Long Click











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









share|improve this question

















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















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









share|improve this question

















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













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









share|improve this question















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






android android-recyclerview kotlin android-view android-navigation-drawer






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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


















  • 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












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





share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    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
































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





    share|improve this answer

























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





      share|improve this answer























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





        share|improve this answer












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






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 11 hours ago









        the_dani

        6211721




        6211721






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            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




















































































            Popular posts from this blog

            Florida Star v. B. J. F.

            Danny Elfman

            Lugert, Oklahoma