I am using following code to drag a View across the screen
tweatBtn.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
float currX,currY;
int action = event.getAction();
switch (action ) {
case MotionEvent.ACTION_DOWN:
{
mPrevX = event.getRawX();
mPrevY = event.getRawY();
btnPrevX = tweatBtn.getX();
btnPrevY = tweatBtn.getY();
break;
}
case MotionEvent.ACTION_MOVE:
{
Display display = getActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth() + 80; // deprecated
int height = display.getHeight(); // deprecated
currX = event.getRawX();
currY = event.getRawY();
if(tweatBtn.getY() > 80 && tweatBtn.getX() > 0 && tweatBtn.getX() < width)
{
tweatBtn.setX(btnPrevX + currX - mPrevX);
tweatBtn.setY(btnPrevY + currY - mPrevY);
}
else
{
if((btnPrevY + currY - mPrevY) > 70 && (btnPrevX + currX - mPrevX) > -10 && tweatBtn.getX() < (width - 10))
{
tweatBtn.setX(btnPrevX + currX - mPrevX);
tweatBtn.setY(btnPrevY + currY - mPrevY);
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
break;
}
return false;
}
});
}
It works fine but sometimes when i lift the Finger it automatically triggers click.How can i improve?
You are returning always false at the end of the code. Which means the touchListener you have set is not handling the touch. Because of if it, View will consider any normal touch as click. What you should do is return True, when the view is dragged, else you should return False
boolean dragged = false;
ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext());
int minTouchSlop = viewConfiguration.getScaledTouchSlop();
.....
public boolean onTouch(View v, MotionEvent event)
{
float currX,currY;
int action = event.getAction();
switch (action ) {
case MotionEvent.ACTION_DOWN:
{
mPrevX = event.getRawX();
mPrevY = event.getRawY();
btnPrevX = tweatBtn.getX();
btnPrevY = tweatBtn.getY();
dragged = false; // global dragged variable
break;
}
case MotionEvent.ACTION_MOVE:
{
Display display = getActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth() + 80; // deprecated
int height = display.getHeight(); // deprecated
currX = event.getRawX();
currY = event.getRawY();
if(Math.abs(currX-mPrevX) > minTouchSlop || Math.abs(currY-mPrevY) > minTouchSlop)
dragged = true; // differntiate btw drag or click
if(tweatBtn.getY() > 80 && tweatBtn.getX() > 0 && tweatBtn.getX() < width)
{
tweatBtn.setX(btnPrevX + currX - mPrevX);
tweatBtn.setY(btnPrevY + currY - mPrevY);
}
else
{
if((btnPrevY + currY - mPrevY) > 70 && (btnPrevX + currX - mPrevX) > -10 && tweatBtn.getX() < (width - 10))
{
tweatBtn.setX(btnPrevX + currX - mPrevX);
tweatBtn.setY(btnPrevY + currY - mPrevY);
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
break;
}
return dragged;
}
Related
I'm having some trouble with handling multi-touch in android game:
when I touch the screen with three or more fingers, remove them, and touch it again I'm getting this error:
java.lang.IllegalArgumentException: pointerIndex out of range, which occurs in this line of code in onTouchEvent : x = (int) event.getX(event.findPointerIndex(a));
Here is the code
#Override
public boolean onTouchEvent(MotionEvent event)
{
//touch positions
int x, y;
//number of touched areas
int num = event.getPointerCount();
//masked touch action
int action = event.getActionMasked();
if(1 < num && num < 3)
{
for (int a = 0; a < num; a++)
{
x = (int) event.getX(event.findPointerIndex(a));
y = (int) event.getY(event.findPointerIndex(a));
switch (action)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
{
if(y > screenY/2) point1.set(x, y);
if(y < screenY/2) point2.set(x, y);
}
}
}
}
else
{
x = (int) event.getX();
y = (int) event.getY();
switch (action)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
{
if(y > screenY/2) point1.set(x, y);
if(y < screenY/2) point2.set(x, y);
}
}
}
return true;
}
When I open my app on the left top corner appears image, when I touch it image starts to move towards bottom right corner. Now when I stop moving my finger (while touching image) image stops as well, how to make image move without interruption?
img.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int X = (int) event.getX();
int Y = (int) event.getY();
int action = event.getAction();
imgX += 1;
imgY += 1;
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (X >= 0 && X <= img.getWidth() && Y >= 0 && Y <= img.getHeight()) {
img.setX(imgX);
img.setY(imgY);
}
else {
finish();
}
break;
case MotionEvent.ACTION_UP:
finish();
break;
}
return true;
}
});
I am trying to add pinch to zoom in my 3D view, and it doesn't work. Rotating is working, but not zooming.
I have also tried with ACTION_POINTER1_UP/DOWN, but that was a fail
Here's my code :
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getPointerCount() > 1)
{
int x1 = (int) event.getX(0);
int y1 = (int) event.getY(0);
int x2 = (int) event.getX(1);
int y2 = (int) event.getY(1);
d = Math.sqrt((x1-x2)^2+(y1-y2)^2);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
rotating = true;
break;
case MotionEvent.ACTION_UP:
rotating = true;
prevSwipeY = swipeY = 0; // for the Y axis
prevSwipeX = swipeX = 0; // for the X axis
break;
case MotionEvent.ACTION_MOVE:
float directionY = (prevSwipeY - event.getX()) * -1;
float directionX = (prevSwipeX - event.getY()) * -1;
swipeY = (int) (directionY * ROTATION_SPEED);
swipeX = (int) (directionX * ROTATION_SPEED);
if(event.getPointerCount() > 1)
{
int x1 = (int) event.getX(0);
int y1 = (int) event.getY(0);
int x2 = (int) event.getX(1);
int y2 = (int) event.getY(1);
d2 = Math.sqrt((x1-x2)^2+(y1-y2)^2);
r = d2/d;
}
break;
}
// Camera pivot point is different
prevSwipeY = (int) event.getX();
prevSwipeX = (int) event.getY();
return super.onTouchEvent(event);
}
#Override
public void updateScene() {
if (faceObject3D != null) { // If an object is loaded
if (swipeY != 0) // and we did swiped in the correct direction
faceObject3D.rotation().y += swipeY;
swipeY = 0; // Reset the pointer
if (swipeX != 0) // and we did swiped in the correct direction
faceObject3D.rotation().x += swipeX;
swipeX = 0; // Reset the pointer
if(r != 0) {faceObject3D.scale().x = faceObject3D.scale().y = faceObject3D.scale().z = (float) (r*2.0f);};
}
}
Do yo know what is missing ?
zoom jumps around when I remove my finger and put it again ! anybody knows the problem ?
boolean surfaceTouchEvent(MotionEvent event) {
pointNum=event.getPointerCount();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
// User is pressing down another finger.
float x11 = event.getX(0) - event.getX(1);
float y22 = event.getY(0) - event.getY(1);
z4 = sqrt(x11*x11+y22*y22);
break;
case MotionEvent.ACTION_POINTER_UP:
// User is released one of the fingers.
break;
case MotionEvent.ACTION_MOVE:
if (pointNum >= 2 ) {
x1=event.getX(0);
x2=event.getX(1);
y1=event.getY(0);
y2=event.getY(1);
float x = event.getX(0) - event.getX(1);
float y= event.getY(0) - event.getY(1);
float z3 = sqrt(x*x+y*y);
if (pointNum >= 2 ) {
if ( z3 < z4 ) {
zoom = z3/z4;
}
else {
zoom = z3/z4;
}
zoom = constrain(zoom, 0, 100);
}
press1=event.getSize(0);
press2=event.getSize(1);
}
break;
}
return super.surfaceTouchEvent(event);
}
The following code is what I've been trying to use for multitouch. Finger one is set correctly and moves around when I drag my finger. Finger two shows up and disappears when I touch and release my finger, but it never moves around. Any idea what's wrong?
I have read developers blog I still do not understand what the issues are.
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int pointerId = event.getPointerId(pointerIndex);
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
if (pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
if (pointerId == 0)
{
fingerOneDown = 0;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 0;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
break;
case MotionEvent.ACTION_MOVE:
if (pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
break;
}
return true;
}
Nevermind this. I fixed it. The ACTION.MOVE event always gets zero as the pointerId for some strange reason. Because of this, you always have to recalculate the pointerId within the event as seen below:
case MotionEvent.ACTION_MOVE:
int pointerCount = event.getPointerCount();
for(int i = 0; i < pointerCount; ++i)
{
pointerIndex = i;
pointerId = event.getPointerId(pointerIndex);
Log.d("pointer id - move",Integer.toString(pointerId));
if(pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if(pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
}
break;