Search code examples
androidtouch

onTouchEvent hold down, continuous execution


In my onTouchEvent() method, I want to perform an action that continues to repeat itself until I lift my finger off the screen. Here is my code:

public void onTouchEvent(MotionEvent event) {
    synchronized (this) {
        Matrix matrix = new Matrix();

        float x = event.getX();
        if (x >= screenWidth / 2) {
            rotate += 10;
        } else {
            rotate -= 10;
        }
        matrix.postRotate(rotate, square.getWidth() / 2, square.getHeight() / 2);
        position.set(matrix);
        position.postTranslate(xPos, yPos);
    }
    return true;
}

But the problem is, if I hold down my finger and do not move it, the action will only perform once. I have tried various solutions, including

boolean actionUpFlag = false;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
    actionUpFlag = true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
    actionUpFlag = false;
}

while (actionUpFlag) {
    //the block of code above        
}

and making the action only perform if the event is MotionEvent.ACTION_MOVE, and returning false at the end of onTouchEvent(), all of which were unsuccessful. Can anyone inform me what the error is?

Block of code for MotionEvent.ACTION_MOVE attempt:

if (event.getAction() == MotionEvent.ACTION_MOVE) {
    //block of code above
}

Solution

  • Have you considered using a Thread to accomplish this?

    It's late here (and I've been working for 13 hours), but this should give you the gist:

    WorkerThread workerThread;
    
    public void onTouchEvent(MotionEvent event){
    
    
        int action = event.getAction();
    
        switch(action){
            case MotionEvent.ACTION_DOWN:
                if (workerThread == null){
                    workerThread = new WorkerThread();
                    workerThread.start();
                }
                break;
            case MotionEvent.ACTION_UP:
                if (workerThread != null){
                    workerThread.stop();
                    workerThread = null;
                }
                break;
            }
        return false;
    }
    

    Your Thread implementation could be an inner class like:

    class WorkerThread extends Thread{
    
        private volatile boolean stopped = false;
    
        @Override
        public void run(){
            super.run();
            while(!stopped){
                //do your work here
            }   
        }
    
        public void stop(){
            stopped = true;
        }
    }
    

    You may just want to ignore MotionEvent.ACTION_MOVE unless you want to perform a different action.

    If you are updating your UI with WorkerThread, make sure you do it in a thread safe manner.

    Here is a link to the Android API Guide on Processes and Threads