1

I have a method being called constantly.

I want the method to have the following:

if(screen is being touched) {
Do this
}
else {
Do this
}

Another way to phrase the question is that I want something to happen as long as the screen is being touched not just something to happen onetime as soon as the screen has been touched.

I looked at this question: detect if the touch stopped on an android device screen

But I got confused by the answer.

Community
  • 1
  • 1
O_O
  • 13
  • 1
  • 5

4 Answers4

6

You can use something like this code

view.setOnTouchListener(new OnTouchListener () {
    public boolean onTouch(View view, MotionEvent event) {
        switch(event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // The user just touched the screen

                break;
            case MotionEvent.ACTION_UP:
                // The touch just ended

                break;
        }

        return false;
    }
});

You should assign this listener to either the root view of a Fragment or a decor view of an Activity. You can obtain this with:

View view = getWindow().getDecorView();

If you don't want just to react to the touch events but rather just know whether screen is being touched in a different method, just assign boolean flag within the listener.

Edit

Since you need to call a method continuously at defined time interval, I suggest to define the interval

final static long REFRESH_TIME = 100; // miliseconds

then create a Handler

final Handler handler = new Handler();

and define Runnable that will get called by the Handler and will call your method

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        // call your method

        handler.postDelayed(this, REFRESH_TIME);
    }
}

In your OnTouchListener you initialize and stop the repeating with

case MotionEvent.ACTION_DOWN:
    handler.post(runnable);
    break;

case MotionEvent.ACTION_UP:
    handler.removeCallbacks(runnable);
    break;
Lamorak
  • 10,957
  • 9
  • 43
  • 57
  • I did something like this in my main method here is the code: [link](http://pastebin.com/h3BnTSS6) The problem is paddleUpdate() is only called when the screen has just been touched. If I hold the touch nothing happens (I want paddleUpdate() to be called as long as the screen is being touched). – O_O Sep 02 '15 at 21:06
  • So you need something like when the screen is touched, `paddleUpdate()` will get called each 100ms (or similar bahavior)? – Lamorak Sep 02 '15 at 21:12
  • I'm surprised there is no simple method to detect if something is touching the screen. That way I could just call a method every 100ms continuously and have a if statement so it only executes a certain piece of code when the screen is being touched. – O_O Sep 03 '15 at 19:35
  • Also I guess I was wrong about it being called every 100ms in reality it should be called every time onDraw() is called. – O_O Sep 03 '15 at 19:37
  • However your solution did help me figure out the answer. I guess your solution works in the case if someone needs to call the method every 100ms. But now I realize the update method should be called when onDraw() is called but a certain piece piece of code in the update method should also be called in addition too the rest of the update method when the screen is being touched. – O_O Sep 03 '15 at 19:46
  • But I have mentioned assigning boolean flag when I first answered :) – Lamorak Sep 03 '15 at 20:07
  • Oh, I guess I was being stupid. Your answer was correct the entire time. – O_O Sep 05 '15 at 12:38
  • No problem the important thing here is that you have solved your problem. – Lamorak Sep 05 '15 at 12:47
  • in order to fire motionEvent.Action_UP you should return true at the end of the event not false. – smoothumut Jun 11 '20 at 17:48
1

One possible way to accomplish your desired result: try put a View on top of your view hierarchy, set it the same size of the screen, then override the setPressed() method of the view. If pressed, do something, if not, do something else:

@Override
    public void setPressed(boolean pressed) {
            if (pressed) {
                do something;
            } else {
                do something else;
            }
        super.setPressed(pressed);
    }
yongsunCN
  • 736
  • 7
  • 18
  • That didn't work. Because pressed would be the value I put in the parameter of the method. I called setPressed(true) in my onDraw method and of course pressed was always true. Am I implementing it wrong? – O_O Sep 02 '15 at 21:00
  • I'm not sure what your goal is and I don't know the other part of your code. But normally I wouldn't call setPressed by myself because in most cases it's handled by the system. When you touch the view, system calls setPressed(true) and when your finger leaves the view it set false. Is there a special reason you want to set value to this method yourself? – yongsunCN Sep 02 '15 at 21:08
  • Thing is setPressed is never called on its own. – O_O Sep 02 '15 at 22:10
0

Try using onTouchListener() and implementing onTouch(View v, MotionEvent e) to check for the events ACTION_UP and ACTION_DOWN.

Implementation example: Touch Release method in Android

Edit:

Reading over some of your discussions with others, I recommend having an AsyncTask in your class that runs your update loop constantly, like so:

private static boolean doUpdate = false;

private class PaddleUpdater extends AsyncTask<String,Void,Void> {
  @Override
  protected Void doInBackground(String... strings) {
    while(true) {
      if(isCancelled()) { break; }
      if(doUpdate) {
        //update paddle
      }
    }
  }
}

//in the constructor, do this
PaddleUpdater pu = new PaddleUpdater();
pu.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

Then setup a BroadcastReceiver in the class like this:

public static final String TOUCH_UPDATE = "com.packagename.intent.action.TOUCH_UPDATE";

private class TouchStateReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context c, Intent i) {
    Bundle b = i.getExtras();
    if (b != null) {
      doUpdate = b.getBoolean("touch");
    }
  }
}

//in the constructor do this
registerReceiver(new UpdateReceiver(), new IntentFilter(TOUCH_UPDATE));

Then, in your main activity, setup your listener as described in @Lamorack's post, but add an intent broadcast:

view.setOnTouchListener(new OnTouchListener () {
  public boolean onTouch(View view, MotionEvent event) {
      Intent i = new Intent(<ClassName>.TOUCH_UPDATE);
      switch(event.getAction()) {
          case MotionEvent.ACTION_DOWN:
              // The user just touched the screen
              i.putExtra("touch", true);
              sendBroadcast(i);
              break;
          case MotionEvent.ACTION_UP:
              // The touch just ended
              i.putExtra("touch", false);
              sendBroadcast(i);
              break;
      }

      return false;
  }
});

Explanation:

So, what you need to do is track a certain state. Android tells you when the screen has been touched, and when it has been released, so we need to track the touch state based on those events. So we've set a boolean to track that state. When the touch case is triggered, we send an Intent over to your class and tell it to change the boolean it is tracking to true. When the released case is triggered, we tell your class to change the boolean it is tracking to false.

The class itself has spun up an AsyncTask that will basically run until you tell it to stop, manually. The loop in the AsyncTask will constantly check the value of the boolean, when it is true, it will do the update, when it is false, it will skip the update.

The BroadcastReceiver we set up in your class is what actually receives the Intents being sent by your touch listener.

Community
  • 1
  • 1
nukeforum
  • 1,284
  • 3
  • 16
  • 38
0

After reading Lamorak's answer I did something very similar. I had a onTouch method with the following:

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            bool = true;
            break;
        case MotionEvent.ACTION_UP:
            bool = false;
            break;
    }

    return true;
}

Then in the update method I had:

if(bool) {
// Do something
}
else {
//Do this
}

The update method was called whenever onDraw() was called (which was continuously).

O_O
  • 13
  • 1
  • 5