1

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 .

How to stop the runnable when the user un touch it ?

Athira
  • 1,177
  • 3
  • 13
  • 35
Navid Abutorab
  • 1,667
  • 7
  • 31
  • 58
  • 1
    are you sure? I tried your code with the simple hello world text view of a newly created project and it's working fine. maybe you should add the view? – Community Feb 21 '19 at 08:28
  • @Community thanks for your help, where should I add the view ? the code is inside an adapter , can it makes the problem ? – Navid Abutorab Feb 21 '19 at 08:40
  • I think, just a simple layout of the viewholder added to the question will do. now that you mention it, it is also possible the adapter is causing this. Are you using a recyclerview? also when do you add the touch listener? – Community Feb 21 '19 at 08:49

2 Answers2

1

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

    });
Htoo Aung Hlaing
  • 2,173
  • 15
  • 26
0

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

Akash Moradiya
  • 3,318
  • 1
  • 14
  • 19