So I have a touch event and it handles ACTION_DOWN and ACTION_UP one by one. For example if I click on the left half of the screen ACTION_DOWN works but not ACTION_UP and same for the right side of the screen. i want to handle both of them simultaneously. If I click on left side and right side at the same time both the event should perform. Can anyone please help me on this.
My code is
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//if user press the screen
if (event.getX() < screenX / 2f) {
flight.isGoingUp = true;
}
break;
case MotionEvent.ACTION_UP:
flight.isGoingUp = false;
if (event.getX() > screenX / 2f) {
flight.toShoot++;
}
break;
}
return true;
}
Edit 1
The screen is split into two half. The left side of the screen is used for flight.isGoingUp = true; and when we release the left side or tap the right helg of the screen flight.isGoingUp = false; and if (event.getX() > screenX / 2f) { flight.toShoot++; } I want ot do such a code that both of them are handled at the same time.
here is the docs to handle multi touch gestures.
https://developer.android.com/training/gestures/multi#java
Here is a very simple example to handle multitouch based on google docs.
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
int index = event.getActionIndex();
System.out.println("The finger # " + index + " is " + getAction(action));
return true;
}
public static String getAction(int action) {
switch (action) {
case MotionEvent.ACTION_DOWN: return "Down";
case MotionEvent.ACTION_MOVE: return "Move";
case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down";
case MotionEvent.ACTION_UP: return "Up";
case MotionEvent.ACTION_POINTER_UP: return "Pointer Up";
case MotionEvent.ACTION_OUTSIDE: return "Outside";
case MotionEvent.ACTION_CANCEL: return "Cancel";
default: return "Unknown";
}
}
Related
I have researched a lot but I couldn't find even a blog that tell about MultiTouch events. All are giving tutorials on single swipe. I wish to apply fling and 2 finger swipe both in same activity.
I got the solution myself after trying and failing a lot
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent: " + event.getAction());
//with the getPointerCount() i'm able to get the count of fingures
if(event.getPointerCount()>1){
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_POINTER_DOWN:
// This happens when you touch the screen with two fingers
mode = SWIPE;
// event.getY(1) is for the second finger
p1StartY = event.getY(0);
p2StartY = event.getY(1);
break;
case MotionEvent.ACTION_POINTER_UP:
// This happens when you release the second finger
mode = NONE;
float p1Diff = p1StartY - p1StopY;
float p2Diff = p2StartY - p2StopY;
//this is to make sure that fingers go in same direction and
// swipe have certain length to consider it a swipe
if(Math.abs(p1Diff) > DOUBLE_SWIPE_THRESHOLD
&& Math.abs(p2Diff) >DOUBLE_SWIPE_THRESHOLD &&
( (p1Diff>0 && p2Diff>0) || (p1Diff < 0 && p2Diff<0) ))
{
if(p1StartY > p1StopY)
{
// Swipe up
doubleSwipeUp();
}
else
{
//Swipe down
doubleSwipeDown();
}
}
this.mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if(mode == SWIPE)
{
p1StopY = event.getY(0);
p2StopY = event.getY(1);
}
break;
}
}
else if(event.getPointerCount() == 1){
//this is single swipe, I have implemented onFling() here
this.gestureObject.onTouchEvent(event);
}
return false;
}
I have an issue in my app where I need to perform a different action based on if one fingers or two fingers are pressed down.
Currently I have the follow code:
#Override
public boolean onTouchEvent(MotionEvent event){
int touchX = (int)event.getX();
int touchY = (int)event.getY();
int action = event.getActionMasked();
//Multitouch
if(event.getPointerCount() > 1 && action == MotionEvent.ACTION_POINTER_DOWN){
System.out.println("2 Finger press");
return true;
}
else if(action == MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_POINTER_DOWN){
if(event.getPointerCount() == 1) {
System.out.println("single finger down");
invalidate();
return true;
}
}
return false;
}
The issue I am having is when I press with 2 fingers, the multitouch part registers, and after that so does the single press.
I did some googling around on ways to fix that and that would be why I am checking on the single touch conditional that action != MotionEvent.ACTION_POINTER_DOWN which I thought would fix the issue. That didn't fix the issue hence I decided to check that event.getPointerCount() == 1, but unfortunately that still causes both lines to print when I press with 2 fingers.
To summarize I need to only call the 2 finger part when 2 fingers are pressed down and not both.
refer to the documentation on "Handling Multi-Touch Gestures". it details exactly what you're looking for.
in essence, each active pointer is assigned an ID when it makes contact with the screen. your solution will should take into account which IDs come into play and are removed by observing various action states.
something a little bit along these lines (but beware compatibility calls for methods like getActionIndex()):
UPDATED CODE SAMPLE
public class MotionActivity extends AppCompatActivity {
private int primaryPointerId = -1;
private int secondaryPointerId = -1;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new FrameLayout(this));
}
#Override
public boolean onTouchEvent(MotionEvent event){
int action = event.getActionMasked();
switch(action) {
case MotionEvent.ACTION_DOWN:
primaryPointerId = event.getPointerId(0);
Log.d(getClass().getName(), "Primary pointer ID == [" + primaryPointerId + "]");
break;
case MotionEvent.ACTION_POINTER_DOWN:
secondaryPointerId = event.getPointerId(event.getActionIndex());
Log.d(getClass().getName(), "Secondary pointer ID == [" + secondaryPointerId + "]");
break;
case MotionEvent.ACTION_MOVE:
if(primaryPointerId > -1 && secondaryPointerId > -1) {
Log.d(getClass().getName(), "Two-point touch...");
} else {
Log.d(getClass().getName(), "One-point touch...");
}
break;
case MotionEvent.ACTION_POINTER_UP:
if(event.getPointerId(event.getActionIndex()) == primaryPointerId) {
primaryPointerId = secondaryPointerId;
}
secondaryPointerId = -1;
break;
case MotionEvent.ACTION_UP:
primaryPointerId = -1;
break;
}
return true;
}
}
I am programing 2D rpg game and I have weird problem. When I use KeyPressed method it happens to call my move method twice which exits to rewrite player position from [10,10] to [10,12] insted of [10,11] and move my player 2 fields. I was looking around the internet and found nothing useful.
For displaying I use Canvas and Runnable with JFrame. A also use Thread
When I used debugger to search what's wrong I found that Keylistener use method
KeyPressed
public void keyPressed(KeyEvent e)
{
((KeyListener)a).keyPressed(e);
((KeyListener)b).keyPressed(e);
}
I believe that KeyListener a and b do the problem but I dont know hot to fix it.
My move method which change Point (x,y)
public void move() {
Point startPlayerPosition = player.getPosition();
Point newPoint = startPlayerPosition;
switch (direction) {
case Direction.NORTH:
newPoint = new Point(startPlayerPosition.x, startPlayerPosition.y - 1);
break;
case Direction.SOUTH:
newPoint = new Point(startPlayerPosition.x, startPlayerPosition.y + 1);
break;
case Direction.WEST:
newPoint = new Point(startPlayerPosition.x - 1, startPlayerPosition.y);
break;
case Direction.EAST:
newPoint = new Point(startPlayerPosition.x + 1, startPlayerPosition.y);
break;
}
playerPos = newPoint;
player.setPosition(newPoint);}
This is my KeyPressed method. I wait for pressing W,A,S,D to to change direction and then I call move() according to direction.
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_W:
playerWalk = true;
direction = Direction.NORTH;
move();
break;
case KeyEvent.VK_S:
playerWalk = true;
direction = Direction.SOUTH;
move();
break;
case KeyEvent.VK_D:
playerWalk = true;
direction = Direction.EAST;
move();
break;
case KeyEvent.VK_A:
playerWalk = true;
direction = Direction.WEST;
move();
break;
}
}
Thanks for Help
I'm making a platfrom game for android and I could use some help with the touch events.
This is my code:
public boolean onTouch(MotionEvent e, int scaledX, int scaledY) {
for (int i = 0; i < object.size(); i++) {
tempObject = object.get(i);
if (tempObject.getId() == ObjectId.Player) {
if (e.getAction() == MotionEvent.ACTION_MOVE) {
if (moveLeft.contains(scaledX, scaledY)) {
tempObject.setMovingLeft(true);
tempObject.setMovingRight(false);
}
if (moveLeftExit.contains(scaledX, scaledY)
&& !moveLeft.contains(scaledX, scaledY)) {
tempObject.setMovingLeft(false);
}
if (moveRight.contains(scaledX, scaledY)) {
tempObject.setMovingRight(true);
tempObject.setMovingLeft(false);
}
if (moveRightExit.contains(scaledX, scaledY)
&& !moveRight.contains(scaledX, scaledY)) {
tempObject.setMovingRight(false);
}
}
if (e.getAction() == MotionEvent.ACTION_UP
|| e.getAction() == MotionEvent.ACTION_OUTSIDE) {
if (moveLeft.contains(scaledX, scaledY)) {
tempObject.setMovingLeft(false);
}
if (moveRight.contains(scaledX, scaledY)) {
tempObject.setMovingRight(false);
}
}
if (e.getAction() == MotionEvent.ACTION_DOWN) {
if (jump.contains(scaledX, scaledY)) {
if(tempObject.getVelY() ==0)
tempObject.setVelY(-15);
}
}
}
}
return true;
}
Everything works great while I use one finger, if I touch the moveRight rectangle the character moves right and when I move my finger away he stopes as expected. The problem is that if I touch a button while touching some other button it wont react to it.
So I guess my question is, how can I modify my code so it will react to multi touch?
Thanks!! :)
Here is a simple code.
public boolean onTouch(View v, MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
int pointerIndex = MotionEventCompat.getActionIndex(event);
int x = (int)MotionEventCompat.getX(event,pointerIndex);
int y = (int)MotionEventCompat.getY(event,pointerIndex);
switch(action)
{
case MotionEvent.ACTION_DOWN:
//
// First finger was touched. Set "pointerIndex" to some value (lets say 0 or -1)
// Save "pointerIndex" corresponding to this touched object.
//
break;
case MotionEvent.ACTION_POINTER_DOWN:
//
// More finger touched when first finger is already touched.
// Save "pointerIndex" corresponding to this touched object.
//
break;
case MotionEvent.ACTION_MOVE:
//
// Finger with "pointerIndex" was moved.
//
break;
case MotionEvent.ACTION_UP:
//
// The first touched finger went off.
//
break;
case MotionEvent.ACTION_POINTER_UP:
//
// Finger with "pointerIndex" went off (other than first finger)
//
break;
}
return true;
}
Good Luck. :)
I am developing a two player Pong game and wish to control the bats, each with one finger. However, my problem is that it only responds to one finger being on the screen at a time. The entire game is ran in one view. First, I check if a pointer is "active" before checking if it occured on the top or bottom of the screen before moving the corresponding bat. It works normally, except for that only one touch registers. My code for the method is below:
// variables
int _touchY = (int) event.getY();
boolean isTopSide = true;
// test if motionEvent was on the top or bottom of the screen
if (SCREEN_HEIGHT / 2 - _touchY < 0) {
isTopSide = false;
}
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
_activePointer = event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
if(_activePointer != INVALID_POINTER_ID) {
if (isTopSide) { // top bat
_topBat.moveBat(event);
} else { // bottom bat
_botBat.moveBat(event);
}
}
if(_newPointer != INVALID_POINTER_ID){
if (isTopSide) { // top bat
_topBat.moveBat(event);
} else { // bottom bat
_botBat.moveBat(event);
}
}
break;
case MotionEvent.ACTION_UP:
if(_activePointer != INVALID_POINTER_ID){
_activePointer = INVALID_POINTER_ID;
}
break;
case MotionEvent.ACTION_CANCEL:
_activePointer = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
int pointerIndex = event.getActionIndex();
int pointerId = event.getPointerId(pointerIndex);
if(pointerId == _activePointer){
_activePointer = INVALID_POINTER_ID;
}
case MotionEvent.ACTION_POINTER_DOWN:
int newPointerIndex = event.getActionIndex();
_newPointer = event.getPointerId(newPointerIndex);
break;
}
Relevant global code
// touched
private static final int INVALID_POINTER_ID = -1;
private int _activePointer = INVALID_POINTER_ID;
private int _newPointer = INVALID_POINTER_ID;
The main problem why you're only seeing values for a single pointer is because event.getY() without any parameter gives you the position for the first pointer index, even if the pointer that actually moved was the second pointer.
The MotionEvent class contains the coordinates for all the active pointers.
If you want to get the second pointer's position, you'll want to call event.getY(1).
You'll probably want to loop through all the active points, getting the total count via event.getPointerCount(), and then send the events accordingly.