0

I'm creating a simple OpenGL 'app' to rotate a triangle. I wish, on the first touch, to save the angle the touch position corresponds to. Then, on motion, rotate the shape by the angle corresponding to current position minus angle of first touch.

It was my understanding that the first step should be done in MotionEvent.ACTION_DOWN, and the second in MotionEvent.ACTION_MOVE. However, it seems as if ACTION_DOWN is being called during the motion. That is, the below code causes the shape to rotate as a finger is dragged (and I understood that it would rotate only to the position of the initial touch):

private double mTheta;      

@Override
public boolean onTouchEvent(MotionEvent e) {

    super.onTouchEvent(e);

    float x = e.getX();
    float y = e.getY();

    switch (e.getAction()) {

    case MotionEvent.ACTION_DOWN:
        x -= getWidth() / 2;
        y -= getHeight() / 2;
        mTheta = Math.atan2(-x,-y) * 180.0f / Math.PI;
        GL20Renderer.mAngle = (float) mTheta;
        requestRender();
    }
    return true;
}

Is my code wrong, or is this some weird behaviour of the emulator? (I don't currently have access to an android device.)

(Addendum: I original attempted to implement the above fully, with a MotionEvent.ACTION_MOVE case for calculating the new angle and rendering. The ACTION_DOWN case was only saving the starting offset angle. This didn't work, in that the shape didn't rotate - because the offset angle was being re-calculated during movement - which is how I ended up at this point.)

Sam
  • 557
  • 6
  • 20
  • I see only ACTION_DOWN. Where is the mentioned ACTION_MOVE? You actually only do something in ACTION_DOWN, nothing (except saving the coords) when ACTION_MOVE – WarrenFaith Feb 02 '13 at 15:19
  • I used to have it (see addendum). My problem is that ACTION_DOWN is being used continuously during a touch-drag-lift movement, when it should only be once, during the first touch (I think?) – Sam Feb 02 '13 at 15:23
  • 1
    Have you tried `getActionMasked()`? Implement all ACTION_UP/DOWN/MOVE and log them to see if MOVE and/or UP are called correctly. – WarrenFaith Feb 02 '13 at 15:27
  • Okay, so using `if (e.getActionMasked() == MotionEvent.ACTION_MOVE) { rotate wrt. offset } else if (e.getActionMasked() == MotionEvent.ACTION_DOWN) { set the offset }` works fine. How is this different from using `e.getAction()` and `switch`/`case`? (Thanks!) – Sam Feb 02 '13 at 15:35
  • 1
    ActionMasked is important for multitouch. You can use switch case with this, too. – WarrenFaith Feb 02 '13 at 15:38
  • Yeah, I just realized what you meant. It works fine now (with if else and switch case), thanks! (Although I missed the fact that on ACTION_UP I also need to save the current rotation sate for the next touch and drag). Anyway, using getActionMasked() solved the problem. – Sam Feb 02 '13 at 15:50

2 Answers2

0

It might have been that you forgot to put a break statement in your switch/case. So once ACTION_MOVE is done, ACTION_DOWN follows immediately after

Andrew Seymour
  • 250
  • 1
  • 4
  • 18
  • I actually tried this, but it didn't help. Solution was as in Warren's comment. Thanks. – Sam Feb 02 '13 at 15:53
0

Needed to be using getActionMasked() rather than getAction(). See comment from WarrenFaith.

Sam
  • 557
  • 6
  • 20