OnTouchEvent logic for surfaceview drawing app - android

Below is a switch case logic for drawing on the surface, it doesn't draw properly. Not sure where am i going wrong. EDIT: class was removed as it was not helpful.
#Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (mThread.getSurfaceHolder()) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_DOWN:
currentDrawingPath = null;
currentDrawingPath = new DrawingPath();
currentDrawingPath.getPath().moveTo(eventX, eventY);
startX = eventX;
startY = eventY;
canvasPaths.add(currentDrawingPath);
//invalidate();
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(eventX - startX);
float dy = Math.abs(eventY - startY);
currentDrawingPath.getPath().quadTo(startX, startY,
(eventX + startX)/2, (eventY + startY)/2);
startX = eventX;
startY = eventY;
//currentDrawingPath.getPath().lineTo(startX, startY);
break;
}
return true;

Following is the code that fixed the issue,
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
currentDrawingPath.getPath().lineTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_DOWN:
currentDrawingPath = new DrawingPath();
currentDrawingPath.setPaintForPath();
// update the starting point of the new path
currentDrawingPath.getPath().moveTo(event.getX(), event.getY());
currentDrawingPath.getPath().lineTo(event.getX(), event.getY());
canvasPaths.add(currentDrawingPath);
break;
case MotionEvent.ACTION_MOVE:
currentDrawingPath.getPath().lineTo(event.getX(), event.getY());
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 draw on image using finger when image zoom?

I am trying to develop draw something on image when image zoom in my project but when zoom then it will be create some offset between touch and drawing but without zoom it is working perfect. For example.
Code for image zoom:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.concat(matrix);
....
}
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
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_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate((event.getX() - start.x), (event.getY() - start.y));
} else if (mode == ZOOM && event.getPointerCount() == 2) {
float newDist = spacing(event);
matrix.set(savedMatrix);
if (newDist > 10f) {
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
if (lastEvent != null) {
float newRot = rotation(event);
float r = newRot - d;
matrix.postRotate(r, view.getMeasuredWidth() / 2, view.getMeasuredHeight() / 2);
}
}
break;
}
invalidate();
return true;
}
Code for drawing:
#Override
public boolean onTouch(View view, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchEnd();
invalidate();
break;
}
return true;
}
private void touchMove(float x, float y) {
float f1 = Math.abs(x - mX);
float f2 = Math.abs(y - mY);
if ((f1 >= 4.0F) || (f2 >= 4.0F)) {
path.quadTo(mX, mY,
(x + mX) / 2.0F,
(y + mY) / 2.0F);
mX = x;
mY = y;
}
}
private void touchStart(float x, float y) {
path.reset();
path.moveTo(x, y);
blurView.pathList.add(path);
blurView.strokeWidthList.add(strokeWidth);
mX = x;
mY = y;
}
private void touchEnd() {
path.lineTo(mX, mY);
path = new Path();
}
can any one help me for how to handle scale factor or how to remove image zoom scale factor into the finger touch.
You usually store the scale factor, and multiplies many of your coordinates handle system by its value.
Simply as that.

Android multitouch: no ACTION_POINTER_DOWN and UP events

Here is my code:
public boolean onTouch(View v, MotionEvent event) {
switch(event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
Log.d("getButtonCode", "catch ACTION_DOWN");
break;
case MotionEvent.ACTION_POINTER_DOWN:
Log.d("getButtonCode", "catch ACTION_POINTER_DOWN");
break;
case MotionEvent.ACTION_POINTER_UP:
Log.d("getButtonCode", "catch ACTION_POINTER_UP");
break;
case MotionEvent.ACTION_UP:
Log.d("getButtonCode", "catch ACTION_UP");
case MotionEvent.ACTION_CANCEL:
Log.d("getButtonCode", "catch ACTION_CANCEL");
case MotionEvent.ACTION_MOVE:
break;
default:
break;
}
return true;
}
and I never catch ACTION_POINTER_DOWN and ACTION_POINTER_UP. If I remove breakfrom ACTION_DOWN, I catch ACTION_POINTER_DOWN always after ACTION_DOWN, even if it is first pointer. I think it should be so: first pointer catch only ACTION_DOWN, every next pointer only ACTION_POINTER_DOWN, if non-primary pointer has gone up, I should catch ACTION_POINTER_UP.
But it doesn't work. What is wrong in my code?
PS: I saw other similar questions, but no answer helped me.
Instead of using a switch statement, I flowed through a series of if statements. This let me test against event.getAction() or event.getActionMasked() and it allowed multiple possible actions through at once.
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
startingX = (int) event.getX();
startingY = (int) event.getY();
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
int scaleX = 1;
int scaleY = 1;
if(touchStateScale == true){
scaleX = (int) (event.getX(0) - event.getX(1));
scaleY = (int) (event.getY(0) - event.getY(1));
}
int endingX = (int) event.getX();
int endingY = (int) event.getY();
int newX = endingX-startingX;
int newY = endingY-startingY;
((ImageView) v).setImageBitmap(drawNewImageScaled(baseImage, newImageResourceId, newX, newY, scaleX, scaleY));
}
if(event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN){
Log.i(TAG, "second pointer detected");
touchStateScale = true;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
touchStateScale = false;
return false;
}
return true;
}
};

Remove the TouchEvent of Button

I want to remove the TouchEvent of Button when the User moves out of the Button Area
I have detected the user movement by:
case MotionEvent.ACTION_DOWN:
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
break;
case MotionEvent.ACTION_MOVE:
if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
logIt("You are OutSide...");
}
break;
Can Anyone Suggest how to do that...
ANy answer Appreciated...Thks
reWrite code like this :-
case MotionEvent.ACTION_DOWN:
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
break;
case MotionEvent.ACTION_UP:
if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
logIt("You are OutSide...");
}
break;
try this...
case MotionEvent.ACTION_DOWN:
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(),v.getBottom());
break;
case MotionEvent.ACTION_MOVE:
if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop()+ (int) event.getY())) {
Log.i(TAG, "You are outside");
return false;
}
break;
and this complete code will give you some idea...
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(),v.getBottom());
break;
case MotionEvent.ACTION_MOVE:
if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop()+ (int) event.getY())) {
Log.i(TAG, "You are outside");
return false;
}
break;
}
return true;
}
Simpliest way :
onTouchEvent(MotionEvent event){
...
case MotionEvent.ACTION_MOVE:
event.setAction(MotionEvent.ACTION_UP);
return super.onTouchEvent(event);
...
}
In That case you will reject all next events related on your button.

MotionEvent.Action_up called to early

I am having an issue with MotionEvent.ACTION_UP The event is called before I lift my finger.
Here is the code I am using. What should I change? Thanks for any help!
public boolean onTouchEvent(MotionEvent e) {
switch(e.getAction()) {
case MotionEvent.ACTION_DOWN:
if(checkColide(e.getX(), e.getY())) {
isFootballTouched = true;
downT = c.MILLISECOND;
downX = e.getX();
}
break;
case MotionEvent.ACTION_MOVE:
//moveFootball(e.getX(), e.getY());
break;
case MotionEvent.ACTION_UP:
upT = c.MILLISECOND;
upX = e.getX();
getVelocity();
break;
}
return false;
}
Try returning true if one of this 3 case occurred
public boolean onTouchEvent(MotionEvent e) {
switch(e.getAction()) {
case MotionEvent.ACTION_DOWN:
if(checkColide(e.getX(), e.getY())) {
isFootballTouched = true;
downT = c.MILLISECOND;
downX = e.getX();
}
return true;
case MotionEvent.ACTION_MOVE:
//moveFootball(e.getX(), e.getY());
return true;
case MotionEvent.ACTION_UP:
upT = c.MILLISECOND;
upX = e.getX();
getVelocity();
return true;
}
return false;
}
Probably you should return true from the onTouchEvent(). Returning false means that you're not interested in receiving events to this View anymore. Hope this helps.

Categories

Resources