I don't understand touch screen event - android

I have the following code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
logArea = (TextView) findViewById(R.id.logArea);
//Tocco
logArea.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(erase) {
logArea.setText("");
counter = 0;
}
logArea.append("DOWN: (" + x + ", " + y + ") ");
counter++;
break;
case MotionEvent.ACTION_MOVE:
logArea.append("MOVE: (" + x + ", " + y + ") ");
counter++;
break;
case MotionEvent.ACTION_UP:
counter++;
logArea.append("UP: (" + x + ", " + y + ") Contatore: " + counter);
erase = true;
break;
}
return true;
}
});
}
Now I run my application and keep still my finger on the screen of the phone. The event perceived is MotionEvent.ACTION_DOWN and also a series of events MotionEvent.ACTION_MOVE. Multiple pairs of points are returned and not only a coordinate pair as I expected.
If I run the application on the simulator is returned only a point and an event MotionEvent.ACTION_DOWN as I expected. Why?
I need necessarily only one point (one in the middle of a finger if possible or close) because I have to read his exact color to do something.
Works on the emulator, not on the device.
What can I do to solve the problem?
Thanks in advance.

What I do to limit the precision of my touch events is to store the last touch, get a delta from the last to the current, and then test if it is past my precision level. I got this idea (and I believe I didn't even have to change the code much) from the SDK samples, so at least in older versions of the platform (pre-multi touch) this was a good recommended practice.
If your issue is happening because of multi touch, you might have to do some tracking with MotionEvent.getPointerXYZ() methods (only considering ACTION_MOVE events associated with the original pointer id you start tracking in your first ACTION_DOWN event)
private float mX, mY;
private static float TOUCH_TOLERANCE = 5;
private void touch_start(float x, float y) {
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
// do my stuff here...
mX = x;
mY = y;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
break;
case MotionEvent.ACTION_UP:
touch_up();
break;
}
return true;
}
http://developer.android.com/reference/android/view/MotionEvent.html#getPointerCount%28%29
http://developer.android.com/reference/android/view/MotionEvent.html#getPointerId%28int%29

Related

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.

dragging an image

I'm trying to make a floating joystick for my android game but am unable to do so.
Here is my onTouch() function:
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
c = holder.lockCanvas();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
float x = event.getX();
float y = event.getY();
Log.d("joystick", " " + x + " " + y);
ondraw(c, x, y);
break;
case MotionEvent.ACTION_MOVE:
d = holder.lockCanvas();
float xdrag = event.getX();
float ydrag = event.getY();
Log.d("joystick move", " " + xdrag + " " + ydrag);
ondraw(d, xdrag, ydrag);
break;
}
return false;
}
for some reason the image is not dragging. can someone tell the problem here and help me?
my ondraw is:
protected void ondraw(Canvas c, float x, float y) {
c.drawColor(Color.BLACK);
c.drawBitmap(bmpback, x - (bmpback.getWidth() / 2),
y - (bmpback.getHeight() / 2), null);
c.drawBitmap(bmpfront, x - (bmpfront.getWidth() / 2),
y - (bmpfront.getHeight() / 2), null);
holder.unlockCanvasAndPost(c);
}
to drag an image something as easy as this works
#Override
public boolean onTouchEvent(MotionEvent event) {
x = event.getX();
y = event.getY();
//Log.d("joy", "x = " + x + "y =" + y);
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(joyback, x - joyback.getWidth() / 2,
y - joyback.getHeight() / 2, null);
super.onDraw(canvas);
}

Drag & Drop for older Android not precise

So I'm attempting to make a "magnetic poetry" type application. Users will move various Button widgets on the screen. I am using a Button widget since it is the closest to the look of the magnet, though I am open to other options!
The objects are not properly moving with my finger. They're close but they're not exactly in line with my finger. The X coordinate on my phone seems to be fine, but the Y corrdinate is off. Is this perhaps due to the title bar?
private final static int DRAGGING_OFF = 0;
private final static int DRAGGING_ON = 1;
private int dragStatus;
private GestureDetector mGestureDetector;
private int mOffsetX;
private int mOffsetY;
private LayoutParams mOldParams;
private RelativeLayout.LayoutParams lp;
#Override
public boolean onTouchEvent(MotionEvent event) {
if(!mGestureDetector.onTouchEvent(event)) {
if(event.getAction() == MotionEvent.ACTION_MOVE) {
if(dragStatus == DRAGGING_ON) {
Log.e(VIEW_LOG_TAG, "Dragging! RAW -- " + event.getRawX() + " : " + event.getRawY() + " NOT RAW -- " + event.getX() + " : " + event.getY());
int rawX, rawY;
int finalX, finalY;
rawX = (int) event.getRawX();
rawY = (int) event.getRawY();
finalX = rawX - mOffsetX;
finalY = rawY - mOffsetY;
lp.setMargins(finalX, finalY, 0, 0);
this.setLayoutParams(lp);
}
return true;
} else if(event.getAction() == MotionEvent.ACTION_UP) {
if(dragStatus == DRAGGING_ON) {
dragStatus = DRAGGING_OFF;
Log.e(VIEW_LOG_TAG, "Stopped dragging!");
}
return true;
} else {
return super.onTouchEvent(event);
}
} else {
return true;
}
}
private final GestureDetector.SimpleOnGestureListener mListener = new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDown(MotionEvent e) {
int[] location = new int[2];
Log.e(VIEW_LOG_TAG, "Down! RAW -- " + e.getRawX() + " : " + e.getRawY() + " NOT RAW -- " + e.getX() + " : " + e.getY());
dragStatus = DRAGGING_ON;
// Sets the current location of the View in the int[] passed to it; x then y.
getLocationInWindow(location);
Log.e(VIEW_LOG_TAG, "Down location: " + location[0] + " " + location[1]);
mOffsetX = (int) e.getRawX() - location[0];
mOffsetY = (int) e.getRawY() - location[1];
mOldParams = getLayoutParams();
return true;
}
};
I think the issue is that you're not getting the DELTA of the current touch point Y and the cached, last touch point y. You need something like this:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView) findViewById(R.id.text);
final ImageView image = (ImageView) findViewById(R.id.image);
matrix.setTranslate(1f, 1f);
image.setImageMatrix(matrix);
image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
matrix.getValues(m); //copy matrix values into array
PointF currentXYTouchPoint = new PointF(event.getX(), event.getY());
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN: //start of pressed gesture
lastXYTouchPoint.set(event.getX(), event.getY()); //save the last touchpoint
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
//calculate the change in finger position
float deltaX = currentXYTouchPoint.x - lastXYTouchPoint.x;
float deltaY = currentXYTouchPoint.y - lastXYTouchPoint.y;
matrix.postTranslate(deltaX, deltaY); //move the entire image by the deltas
image.setImageMatrix(matrix);
// save this last starting touchpoint
lastXYTouchPoint.set(currentXYTouchPoint.x, currentXYTouchPoint.y);
break;
}
textView.setText("TouchPoint started at " + currentXYTouchPoint.x + ", " + currentXYTouchPoint.y + " & the matrix is now " + Arrays.toString(m));
return true;
}
});
}
Adapt it to your own purposes, but the basic idea is there.

Imageview issue with zoom in and out,drag with maximum and minimum levels

I had implemented an image view with the zoom and drag functionalities.I am using matrix for the zoom and drag functionality.But my problem is that I cant set my minimum and maximum zoom level and the drag space limit.can any on e tell me how I can do that.
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 float spacing(PointF start,PointF end)
{
float x = end.x- start.x;
float y = end.y -start.y;
return FloatMath.sqrt(x * x + y * y);
}
#Override
public boolean onTouch(View v, MotionEvent event)
{
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
float scale;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG" );
mode = DRAG;
break;
case MotionEvent.ACTION_UP:
if(mode==DRAG)
{
PointF end=new PointF();
end.set(event.getX(), event.getY());
Log.d("Fling", "Inside the Action Key UP"+spacing(start, end));
float []x = new float[9],org=new float[9];
matrix.getValues(x);
orgMatrix.getValues(org);
Log.d("Fling", "matrixValue"+matrix);
Log.d("Fling", "OrgmatrixValue"+orgMatrix);
float matrixSizex=x[Matrix.MSCALE_X];
float matrixSizey=x[Matrix.MSCALE_Y];
float matrixOrgSizex=org[Matrix.MSCALE_X];
float matrixOrgSizey=org[Matrix.MSCALE_Y];
if(Math.abs(matrixOrgSizex-matrixSizex)<0.17f&&Math.abs(matrixOrgSizey-matrixSizey)<0.17f)
{
Log.d("Fling", "Current Size is equal");
if(spacing(start, end)>30.f)
{
if((start.x>end.x+30)&&(Math.abs(start.y-end.y)<50.0f))
{
Log.d("Fling", "Is From Right To left");
loadedimage.setImageMatrix(orgMatrix);
leftSwipe();
view.setScaleType(ImageView.ScaleType.FIT_XY);
}
else if((end.x>start.x+30)&&(Math.abs(end.y-start.y)<50.0f))
{
Log.d("Fling", "Is From Left To Right");
loadedimage.setImageMatrix(orgMatrix);
rightSwipe();
view.setScaleType(ImageView.ScaleType.FIT_XY);
}
}
}
}
case MotionEvent.ACTION_POINTER_UP: //second finger lifted
mode = NONE;
Log.d(TAG, "mode=NONE" );
break;
case MotionEvent.ACTION_POINTER_DOWN: //second finger down
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 5f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM" );
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
//movement of first finger
PointF end=new PointF();
end.set(event.getX(), event.getY());
Log.d("Fling", "Inside the Action Key UP"+spacing(start, end));
float []x = new float[9],org=new float[9];
matrix.getValues(x);
orgMatrix.getValues(org);
Log.d("Fling", "matrixValue"+matrix);
Log.d("Fling", "OrgmatrixValue"+orgMatrix);
float matrixSizex=x[Matrix.MSCALE_X];
float matrixSizey=x[Matrix.MSCALE_Y];
float matrixOrgSizex=org[Matrix.MSCALE_X];
float matrixOrgSizey=org[Matrix.MSCALE_Y];
if(Math.abs(matrixOrgSizex-matrixSizex)>=0.17f&&Math.abs(matrixOrgSizey-matrixSizey)>=0.17f)
{
matrix.set(savedMatrix);
if (view.getLeft() >= 0)
{
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
}
}
}
else if (mode == ZOOM) { //pinch zooming
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 5f) {
matrix.set(savedMatrix);
scale = newDist / oldDist; //thinking i need to play around with this value to limit it**
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
// Perform the transformation
view.setImageMatrix(matrix);
return true; // indicate event was handled
}
My Sample code is here can any one help me in setting minimum and maximum zoom and drag level.I also have problem when I touch in the image view it automatically get zoomed when converted to the matrix I cant make it stay fit in the device screen.I am totally stuck here........
To restrict zooming I compare the zoomed matrix with the identity matrix and don't assign it to my ImageView if it's smaller than the identity matrix, in which case I reset the scaled matrix back to the identity matrix. I'm using Mono for Android but I guess it will be almost the same in Java:
//check that zoom is not too small
if (Utils.SmallerThanIdentity(matrix))
{
ResetView(v);
}
Where SmallerThanIdentity is implemented:
public static bool SmallerThanIdentity(Android.Graphics.Matrix m)
{
float[] values = new float[9];
m.GetValues(values);
return ((values[0] < 1.0) || (values[4] < 1.0) || (values[8] < 1.0));
}
And here's ResetView. I have Java code for that:
public void resetView(View v)
{
ImageView view = (ImageView)v;
matrix = new Matrix();
view.setScaleType(ImageView.ScaleType.MATRIX);
view.setImageMatrix(matrix);
}
Regarding scroll, I use the ShouldScroll method below before translating the matrix to the area where I want to restrict the scrolling.
private bool ShouldScroll(Android.Graphics.Matrix matrix)
{
float[] values = new float[9];
matrix.GetValues(values);
float[] oldValues = new float[9];
oldMatrix.GetValues(oldValues);
float zoomPercentX = values[0] / oldValues[0];
float zoomPercentY = values[4] / oldValues[4];
float tmpW = -(this.Drawable.IntrinsicWidth / 2) * zoomPercentX;
float tmpH = -(this.Drawable.IntrinsicHeight / 2) * zoomPercentY;
return (values[2] < 0.0f) && (values[2] > tmpW) && //horizontal coordinates
(values[5] < 0.0f) && (values[5] > tmpH); //vertical coordinates
}

How to read a pdf file from left to right position without scrolling up & down in android emulator(pdf viewer)?

I created a pdf viewer for android, in that the pdf files are open in scrolling position(up and down) but i need it in left to right position. I tried it in various combos but it's failed to open.
try this code
/**
* Handle touch event coming from Android system.
*/
public boolean onTouch(View v, MotionEvent event) {
this.lastControlsUseMillis = System.currentTimeMillis();
Log.v(TAG, ""+event.getAction());
if (!gestureDetector.onTouchEvent(event)) {
Log.v(TAG, ""+event.getAction());
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.e(TAG, " - DOWN -");
Log.e(TAG, " getX: " + event.getX());
downX = event.getX();
downY = event.getY();
lastX = downX;
lastY = downY;
lockedVertically = verticalScrollLock;
maxExcursionY = 0;
scroller = null;
}
else if
(event.getAction() == MotionEvent.ACTION_UP){
Log.e(TAG, " - UP -");
Log.e(TAG, " getY: " + event.getY());
}
else if (event.getAction() == MotionEvent.ACTION_MOVE){
if (lockedVertically && unlocksVerticalLock(event))
lockedVertically = false;
float dx = event.getX() - lastX;
float dy = event.getY() - lastY;
float excursionY = Math.abs(event.getY() - downY);
if (excursionY > maxExcursionY)
maxExcursionY = excursionY;
if (lockedVertically)
dx = 0;
doScroll((int)-dx, (int)-dy);
lastX = event.getX();
lastY = event.getY();
}
}
return true;
}
I neaded Horizontal Scrolling with paging once and came across this,
With this class you can add views in code and swipe through them.
Hope this helps

Categories

Resources