Android : How to Allow Only One Touch? - android

How to allow only one touch on Android? I don't want to support multi-touch and I want my app to discard other touches if my one of my fingers is already touching the screen. It's like using exclusive touch on iOS.
Also, is there a way to set the number of touches allowed?
Thanks!
EDIT:
Minimum target API = 8.

yes you can disable the multi-touch by using this android:splitMotionEvents="false" or android:windowEnableSplitTouch="false"

You will have to keep track of the pointer id of the first touch and use only the touch events corressponding to that touch. Here is good example from The official Android blog "Making Sense of Multitouch "
private static final int INVALID_POINTER_ID = -1;
// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;
// Existing code ...
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
mLastTouchX = x;
mLastTouchY = y;
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
// Extract the index of the pointer that left the touch sensor
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}

Related

OnTouchEvent , my scene go back if i touch some place in scene

my question can be pretty strange, but I can not understand why my scene is moving back, if I touch the screen elsewhere, please help me figure it out.
https://youtu.be/oKdwqn0HC0Y - in this video record my problem,
To better understand the problem
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
return true;
}
switch (event.getPointerCount()) {
case 3:
Log.e("Event", "PointerCount = " +event.getPointerCount());
return mScaleDetector.onTouchEvent(event);
case 2:
Log.e("Event", "PointerCount = " +event.getPointerCount());
return doRotationEvent(event);
case 1:
Log.e("Event", "PointerCount = " +event.getPointerCount());
return doMoveEvent(event);
}
return true;
}
private boolean doMoveEvent(MotionEvent event)
{
final int action = event.getAction();
Log.e("doMoveEvent", "action = " +action);
switch (action) {
case MotionEvent.ACTION_DOWN: {
Log.e("doMoveEvent", "action_down");
final float x = event.getX();
Log.e("doMoveEvent", " x = " +x);
final float y = event.getY();
Log.e("doMoveEvent", " y = " +y);
// Remember where we started
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
final float x = event.getX();
final float y = event.getY();
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
Log.e("doMoveEvent", " DX = " +dx);
Log.e("doMoveEvent", " DY = " +dy);
renderer.angleX += dy;
renderer.angleY += dx;
mLastTouchX = x;
mLastTouchY = y;
// Invalidate to request a redraw
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
}
return true;
}
I solved my problem this way
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
final float x = event.getX(); //(NEW)
final float y = event.getY(); //(NEW)
mLastTouchX = x; //(NEW)
mLastTouchY = y; //(NEW)
return true;
}
switch (event.getPointerCount()) {
case 3:
Log.e("Event", "PointerCount = " +event.getPointerCount());
return mScaleDetector.onTouchEvent(event);
case 2:
Log.e("Event", "PointerCount = " +event.getPointerCount());
return doRotationEvent(event);
case 1:
Log.e("Event", "PointerCount = " +event.getPointerCount());
return doMoveEvent(event);
}
return true;
}

How to implement “Two Finger Drag or Scale” of canvas in Android?

I want to implement dragging and scaling of canvas on two finger.
I have tried with following approach.
Step 1 : onTouchEvent i have checked if getPointerCount == 2 then do dragging of canvas similar to single finger dragging.
Code:
if(ev.getPointerCount() == 2) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN: {
final float x = ev.getX(0);
final float y = ev.getY(0);
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
final float x = ev.getX(0);
final float y = ev.getY(0);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
//invalidate();
break;
}
case MotionEvent.ACTION_UP: {
Log.i(TAG,"Double Touch : ACTION_UP SingleTouch:"+isSingleTouch );
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
Log.i(TAG,"Double Touch : ACTION_CANCEL SingleTouch:"+isSingleTouch );
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
Log.i(TAG,"Double Touch : ACTION_POINTER_UP SingleTouch:"+isSingleTouch );
// Extract the index of the pointer that left the touch sensor
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
Step 2: add Scale Gesture Detector
Code:
public boolean onTouchEvent(MotionEvent ev) {
mScaleDetector.onTouchEvent(ev);
/*Some code */
}

How to invoke a service on pinch to zoom in android

I'm wandering that is it possible to invoke a service on pinch to zoom in/out in android, please don't mind if this is a silly doubt for you, please help me in understanding.
startService(MyService);
How to invoke this service on pinch to zoom in on top of any activity.
To detect pinch to zoom I'm using the following code in my MainActivity
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
mLastTouchX = x;
mLastTouchY = y;
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
// Extract the index of the pointer that left the touch sensor
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
Knowledge sharing would be highly appreciated. Thanks in advance.

Whenever I try to rotate imageview, it only rotates on axis

So I have been attempting to create a program that can drag, zoom and rotate a photo. The big problem I seem to be running into is that whenever I try to rotate the photo, it rotates along the corner, rather than around the center. This means that as I try to rotate the image, it quickly leaves my fingers.
Another big problem I have is that every time I touch with two fingers, the image resets to being perfectly upright, instead of the angle it held when i touched it.
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
//if(mode==DRAG)
canvas.translate(mPosX, mPosY);
if (myScale.isInProgress()) {
canvas.scale(mScaleFactor, mScaleFactor, myScale.getFocusX(), myScale.getFocusY());
}
else{
canvas.scale(mScaleFactor, mScaleFactor, mLastGestureX, mLastGestureY);
}
if (myScale.isInProgress()) {
canvas.rotate(degrees, myScale.getFocusX(), myScale.getFocusY());
}
else{
canvas.rotate(degrees, mLastGestureX, mLastGestureY);
}
//canvas.setMatrix(matrix);
//setImageMatrix(matrix);
super.onDraw(canvas);
canvas.restore();
//canvas.drawBitmap(,matrix,new Paint());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if(event.getPointerCount()>1){
myScale.onTouchEvent(event);
}
switch (event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN: {
savedMatrix.set(matrix);
final float x = event.getX();
final float y = event.getY();
mode=DRAG;
// Remember where we started
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = event.getPointerId(0);
lastEvent = null;
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
oldDist = spacing(event);
//savedMatrix.set(matrix);
//midPoint(mid, event);
Log.d("touchResponse: ", "mode=ZOOM");
final float gx = myScale.getFocusX();
final float gy = myScale.getFocusY();
mLastGestureX=gx;
mLastGestureY=gy;
mode=ZOOM;
lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
d = rotation(event);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = event.findPointerIndex(mActivePointerId);
final float x = event.getX(pointerIndex);
final float y = event.getY(pointerIndex);
// Calculate the distance moved
if(!myScale.isInProgress()&&mode==DRAG){
// Move the object
float dx = x-mLastTouchX;
float dy = y-mLastTouchY;
mPosX+=dx;
mPosY+=dy;
// Remember this touch position for the next move event
// Invalidate to request a redraw
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
if(event.getPointerCount()==2){
if (lastEvent!=null){
newRot=rotation(event);
degrees = newRot-d;
}
}
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
}
case MotionEvent.ACTION_POINTER_UP: {
// Extract the index of the pointer that left the touch sensor\
mode=NONE;
mode = NONE;
lastEvent = null;
final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = event.getX(newPointerIndex);
mLastTouchY = event.getY(newPointerIndex);
mActivePointerId = event.getPointerId(newPointerIndex);
}
invalidate();
break;
}
}
return true;
}
//this is a method i ripped from a tutoriaql
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
//matrix=temp;
invalidate();
return true;
}
}
private float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
//if (Constant.TRACE) Log.d("Rotation ~~~~~~~~~~~~~~~~~", delta_x+" ## "+delta_y+" ## "+radians+" ## "
// +Math.toDegrees(radians));
Log.d("Rotation ~~~~~~~~~~~~~~~~~", delta_x+" ## "+delta_y+" ## "+radians+" ## "
+Math.toDegrees(radians));
return (float) Math.toDegrees(radians);
}
If you want to rotate around the center, you need to translate to the center first. That will set the new origin as the center of the image, and rotate always rotates around the origin.

Multitouch Android - Using Half the Screen for One finger and Half for the other

Hi im making a split screen game and i cannot figure out how to get the controls down. Right now they work fine if only one person is touching the screen but once multiple do the first person to touch is the only one who can control. So i need to implement multitouch. I cant figure out how to do it so once one finger is down controlling the object on the top half of the screen another finger can be put down controlling the bottom half of the screen. How should i do this?
EDIT:
I changed it, it still doesnt work though could somebody tell me why
My attempt that doesnt work:
public boolean onTouch(View v, MotionEvent event){
//needs multitouch
if(checkInGame()){
if(event.getY() < this.getMeasuredHeight() / 2){
pointerId1 = event.getPointerId(event.getActionIndex());
}else{
pointerId2 = event.getPointerId(event.getActionIndex());
}
switch(event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_MOVE:{
if(event.getPointerId(event.getActionIndex()) == pointerId1){
Log.d("Touch","Move1");
int pointerIndex = event.getActionIndex();
int moveX = 0;
int moveY = 0;
moveX = (int) event.getX(pointerIndex) - sX;
moveY = (int) event.getY(pointerIndex) - sY;
ship1.setLoc(moveX, moveY);
sX = sX + moveX;
sY = sY + moveY;
}else if(event.getPointerId(event.getActionIndex()) == pointerId2){
int pointerIndex = event.getActionIndex();
Log.d("Touch","Move2");
int moveX = 0;
int moveY = 0;
moveX = (int) event.getX(pointerIndex) - sX2;
moveY = (int) event.getY(pointerIndex) - sY2;
ship2.setLoc(moveX, moveY);
sX2 = sX2 + moveX;
sY2 = sY2 + moveY;
}
return true;
}
case MotionEvent.ACTION_DOWN: {
if(event.getPointerId(event.getActionIndex()) == pointerId1){
Log.d("Touch","Top1");
int pointerIndex = event.getActionIndex();
sX = (int) event.getX(pointerIndex);
sY = (int) event.getY(pointerIndex);
}else if(event.getPointerId(event.getActionIndex()) == pointerId2){
int pointerIndex = event.getActionIndex();
Log.d("Touch","Bottom1");
sX2 = (int) event.getX(pointerIndex);
sY2 = (int) event.getY(pointerIndex);
}
return true;
}
case MotionEvent.ACTION_POINTER_DOWN:{
if(event.getPointerId(event.getActionIndex()) == pointerId1){
Log.d("Touch","Top2");
int pointerIndex = event.getActionIndex();
sX = (int) event.getX(pointerIndex);
sY = (int) event.getY(pointerIndex);
}else if(event.getPointerId(event.getActionIndex()) == pointerId2){
int pointerIndex = event.getActionIndex();
Log.d("Touch","Bottom2");
sX2 = (int) event.getX(pointerIndex);
sY2 = (int) event.getY(pointerIndex);
}
return true;
}
}
You probably want to track each pointer by its ID. On pointer down, check the ID so you know that pointer with ID 1 is controlling object 1. Give this Android blog post a read, it may help: http://android-developers.blogspot.co.uk/2010/06/making-sense-of-multitouch.html

Categories

Resources