简体   繁体   中英

ACTION_UP is not triggered for a quick/normal click on OnTouchListener.onTouch

I have a button to trigger some action in MainActivity and I want to draw animation as follows: when user holds the button (ACTION_DOWN) it scales down, when the button is released (ACTION_UP or ACTION_CANCEL) it scales up and go back to its normal state.

This works great when user holds the button for some time, but for a normal click, ACTION_UP never gets called even though ACTION_DOWN does.

I searched in the documentation and checked almost every answer on stackoverflow but didn't find anything useful.

Here's what the documentation says: "While the framework tries to deliver consistent streams of motion events to views, it cannot guarantee it. Some events may be dropped or modified by containing views in the application before they are delivered thereby making the stream of events inconsistent. Views should always be prepared to handle ACTION_CANCEL and should tolerate anomalous situations such as receiving a new ACTION_DOWN without first having received an ACTION_UP for the prior gesture."

And here's my code:

button.setOnTouchListener { view, event ->
            when(event?.action){
                //behaves as expected
                MotionEvent.ACTION_DOWN -> {
                    scaleDown(view)
                }
                //the problem here: ACTION_UP gets called only when user holds the button for some time
                //and not for a quick/ normal click.
                MotionEvent.ACTION_UP -> {
                    scaleUp(view)
                    doSomething()
                }
                //behaves as expected
                MotionEvent.ACTION_CANCEL -> {
                    scaleUp(view)
                }
            }
            true
        }

I have two questions, First: why ACTION_UP never gets called for a quick/normal click?

Second: how to differentiate between normal click and when user holds the button for some time if i want to react in two different ways?

Question#1

I tried the below snippet and it was working as expected with long, normal, and quick clicks

button.setOnTouchListener { view, event ->

    if (event.action == MotionEvent.ACTION_DOWN) {
        Log.d("TESTOOO", "DOWN")
    } else if (event.action == MotionEvent.ACTION_UP) {
        Log.d("TESTOOO", "UP")
    }

    true
}

在此处输入图像描述

Question#2

Can you try setOnLongClickListener() , I tried it and worked fine

在此处输入图像描述

Answering my own question:

For the first question, the problem was with the animation not the OnTouchListener.

For the second question, to differentiate between a normal click and a long click, i had to calculate how many milliseconds have passed since ACTION_DOWN was triggered when ACTION_UP or ACTION_CANCEL is triggered.

If the difference between the two events is less than 300 milliseconds it's considered a normal click, else it's a long click.

button.setOnTouchListener { view, event ->
    val now = System.currentTimeMillis()
    when(event?.action){
        MotionEvent.ACTION_DOWN -> {
            scaleDown(view)
        }
        MotionEvent.ACTION_UP -> {
             scaleUp(view)
             if(now - event.downTime < 300){
                 //normal click
             }else{
                 //long click
             }
        }
        MotionEvent.ACTION_CANCEL -> 
             scaleUp(view)
        }
   }
   true
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM