简体   繁体   English

android - 从未调用 MotionEvent.ACTION_UP

[英]android - MotionEvent.ACTION_UP is never called

I want to do some works while the user hold his hand on a view and stop it when he release it.我想做一些工作,而用户将手放在视图上并在他松开时停止。 My code is below:我的代码如下:

viewHolder.plus.setOnTouchListener(new View.OnTouchListener() {
        private Handler mHandler;
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch(event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if(mHandler==null)
                        mHandler = new Handler();
                    mHandler.postDelayed(mAction, 500);
                    return true;
                case MotionEvent.ACTION_UP:
                    Log.v("this","cancel");
                    if (mHandler != null) {
                        mHandler.removeCallbacks(mAction);
                        mHandler = null;
                        Log.v("this", "c cancel");
                    }
                    break;
            }
            return false;
        }

        Runnable mAction = new Runnable() {
            @Override public void run() {
                ChangeTedad(item.getid(), "plus");
                Log.v("this","Cc");
                mHandler.postDelayed(this, 500);
            }
        };

    });

the problem is, ACTION_UP is never called and the runnable stays run forever.问题是,永远不会调用 ACTION_UP 并且 runnable 会永远运行。

How to stop the runnable when the user un touch it?当用户取消触摸时如何停止运行?

You have not properly set break and return flag in touch event. 您没有在触摸事件中正确设置中断和返回标志。

Please replace your code with, 请替换为您的代码,

viewHolder.plus.setOnTouchListener(new View.OnTouchListener() {
        private Handler mHandler;
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch(event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if(mHandler==null)
                        mHandler = new Handler();
                    mHandler.postDelayed(mAction, 500);
                    break;
                case MotionEvent.ACTION_UP:
                    Log.v("this","cancel");
                    if (mHandler != null) {
                        mHandler.removeCallbacks(mAction);
                        mHandler = null;
                        Log.v("this", "c cancel");
                    }
                    break;
            }
            return true;
        }

        Runnable mAction = new Runnable() {
            @Override public void run() {
                ChangeTedad(item.getid(), "plus");
                Log.v("this","Cc");
                mHandler.postDelayed(this, 500);
            }
        };
    });

Hope this will help you 希望这个能对您有所帮助

Whenever you do a single touch in a view, Android will create a series of touch events instead of a single touch event and buffer these events then call onTouch method sequentially based on returned value from that method. 每当您在视图中进行单次触摸时,Android都会创建a series of touch events而不是a single touch event并缓冲这些事件,然后根据该方法返回的值顺序调用onTouch方法。

For example when you do a single touch on a view, the normal sequence of events will be 例如,当您对视图进行一次触摸时,正常的事件顺序将是

  • ACTION_DOWN (when you put your finger down) ACTION_DOWN (当您放下手指时)
  • optionally ACTION_MOVE (if you move your finger while touching the screen) (可选) ACTION_MOVE (如果您在触摸屏幕时移动手指)
  • ACTION_UP (when you remove your finger from the screen) ACTION_UP (从屏幕上移开手指时)

However, if you return false from the onTouchEvent override in response to an ACTION_XXX event, you will not be notified (your code will not be executed) about any subsequent events. 但是,如果您响应ACTION_XXX事件而从onTouchEvent覆盖返回false ,则不会通知您任何后续事件(您的代码将不执行)。

Back to your case, because you return false from onTouchEvent , so after receiving first event ( ACTION_DOWN ), all subsequent events (including ACTION_UP ) will not be called. 回到您的情况,因为您从onTouchEvent返回false ,所以在接收到第一个事件( ACTION_DOWN )之后,将不调用所有后续事件(包括ACTION_UP )。

All you need to do is return true from onTouchEvent method. 您需要做的就是从onTouchEvent方法返回true That's it! 而已!

viewHolder.plus.setOnTouchListener(new View.OnTouchListener() {
    private Handler mHandler;

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        switch(event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (mHandler == null) {
                    mHandler = new Handler();
                }
                mHandler.postDelayed(mAction, 500);
                break;
            case MotionEvent.ACTION_UP:
                Log.v("this","cancel");
                if (mHandler != null) {
                    mHandler.removeCallbacks(mAction);
                    mHandler = null;
                    Log.v("this", "c cancel");
                }
                break;
        }

        // [IMPORTANT] Return true here
        return true;
    }

    Runnable mAction = new Runnable() {
        @Override public void run() {
            ChangeTedad(item.getid(), "plus");
            Log.v("this","Cc");
            mHandler.postDelayed(this, 500);
        }
    };
}); 

This is a really good post that explains about touch handing in Android. 是一篇非常不错的文章,介绍了Android中的触摸处理。 Take a look at it when you have time. 有空的时候看看吧。

You can also add your ACTION_UP logic codes to ACTION_CANCEL , cause of, if you touch the view and release it, it will call to ACTION_UP , but if you are at view pressed state and you move even 1 Pixel, it will NOT call ACTION_UP , and call only ACTION_CANCEL .您还可以将ACTION_UP逻辑代码添加到ACTION_CANCEL ,因为如果您触摸视图并释放它,它将调用ACTION_UP ,但是如果您在视图中按下 state 并且您移动了 1 个像素,它不会调用ACTION_UP ,并且只调用ACTION_CANCEL Hope this will help for you.希望这对您有所帮助。

viewHolder.plus.setOnTouchListener(new View.OnTouchListener() {
        private Handler mHandler;
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch(event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if(mHandler==null)
                        mHandler = new Handler();
                    mHandler.postDelayed(mAction, 500);
                    return true;
                case MotionEvent.ACTION_UP:
                    Log.v("this","cancel");
                    if (mHandler != null) {
                        mHandler.removeCallbacks(mAction);
                        mHandler = null;
                        Log.v("this", "c cancel");
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    Log.v("this","cancel");
                    if (mHandler != null) {
                        mHandler.removeCallbacks(mAction);
                        mHandler = null;
                        Log.v("this", "c cancel");
                    }
                    break;
            }
            return false;
        }

        Runnable mAction = new Runnable() {
            @Override public void run() {
                ChangeTedad(item.getid(), "plus");
                Log.v("this","Cc");
                mHandler.postDelayed(this, 500);
            }
        };

    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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