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);
}
Related
i have relative parent layout and adding custom textview dynamically into it. when i drag(move) and scale my current textview it get weird jumps continuously in both pointer index. how can i solve this issue?
my custom textview as given below:
public class VideoTextView extends TextView implements View.OnTouchListener {
private final String TAG = this.getClass().getSimpleName();
private Context context;
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
private PointF start = new PointF();
private PointF mid = new PointF();
private float[] matrixValues = new float[9];
private Paint paint;
private Paint linePaint;
private VideoTextMovement videoTextMovement;
private OperationListener operationListener;
private int widthView, heightView;
private boolean isInEdit;
public VideoTextView(Context context, int widthView, int heightView) {
super(context);
this.context = context;
this.widthView = widthView;
this.heightView = heightView;
videoTextMovement = (VideoTextMovement) context;
init();
}
public void updateViewWidthHeight(int widthView, int heightView) {
this.widthView = widthView;
this.heightView = heightView;
}
private void init() {
paint = new Paint();
paint.setTextSize(8);
paint.setColor(context.getResources().getColor(R.color.white));
linePaint = new Paint();
linePaint.setColor(getResources().getColor(R.color.colorPrimary));
linePaint.setAntiAlias(true);
linePaint.setDither(true);
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setStrokeWidth(3.0f);
// setTextSize(8f);
setTextColor(getResources().getColor(R.color.colorAccent));
setOnTouchListener(this);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int textWidth = getMeasuredWidth();
int textHeight = getMeasuredHeight();
int origWidth = textWidth;
int origHeight = textHeight;
matrix.getValues(matrixValues);
canvas.save();
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG & Paint.FILTER_BITMAP_FLAG));
float transX = matrixValues[Matrix.MTRANS_X];
float transY = matrixValues[Matrix.MTRANS_Y];
float scaleX = matrixValues[Matrix.MSCALE_X];
float scaleY = matrixValues[Matrix.MSCALE_Y];
float maxScale = widthView / textWidth;
Log.e(TAG + " ====", "matrix scale " + scaleX + " " + scaleY + " max scale " + maxScale);
scaleX = Math.max(0.5f, Math.min(scaleX, maxScale));
scaleY = Math.max(0.5f, Math.min(scaleY, maxScale));
if (scaleX > 1.0f) {
textWidth = (int) (textWidth + (textWidth * (scaleX - 1.0f)));
} else if (scaleX < 1.0f) {
textWidth = (int) (textWidth * scaleX);
}
if (scaleY > 1.0f) {
textHeight = (int) (textHeight + (textHeight * (scaleY - 1.0f)));
} else if (scaleY < 1.0f) {
textHeight = (int) (textHeight * scaleY);
}
Log.e(TAG + " ====", "original Tx-Ty " + transX + " - " + transY);
if (transX < 0) {
transX = 0;
}
if (transY < 0) {
transY = 0;
}
if (transX > (widthView - textWidth)) {
transX = widthView - textWidth;
}
if (transY > (heightView - textHeight)) {
transY = heightView - textHeight;
}
Log.e(TAG + " ====", "original w-h " + origWidth + " - " + origHeight + " " + " increased w-h " + textWidth + " - " + textHeight);
Log.e(TAG + " ====", "diff w-h " + Math.abs(origWidth - textWidth) + " - " + Math.abs(origHeight - textHeight));
matrixValues[Matrix.MTRANS_X] = transX;
matrixValues[Matrix.MTRANS_Y] = transY;
matrixValues[Matrix.MSCALE_X] = scaleX;
matrixValues[Matrix.MSCALE_Y] = scaleY;
matrix.setValues(matrixValues);
setX(transX + (textWidth - origWidth) / 2);
setY(transY + (textHeight - origHeight) / 2);
setScaleX(scaleX);
setScaleY(scaleY);
// setPivotX(mid.x);
// setPivotY(mid.y);
Log.e(TAG + " ====", "translateFactor " + transX + " - " + transY + " scaleFactor " + scaleX + " - " + scaleY);
videoTextMovement.translateText(getId(), transX, transY, textWidth, textHeight, getTextSize());
if (isInEdit) {
canvas.drawLine(0, origHeight, origWidth, origHeight, linePaint);
}
canvas.restore();
Log.e(TAG + " ===", TAG + " onDraw");
}
public void midPoint(MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
Log.e(TAG + " ====", "mid point x-y " + (x / 2) + " " + (y / 2));
mid.set(x / 2, y / 2);
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
Log.e(TAG + " ====", "spacing x-y " + (x * x + y * y));
return (float) Math.sqrt(x * x + y * y);
}
float rawX0;
float rawY0;
float rawX1;
float rawY1;
private void getOriginalLocation(MotionEvent event) {
int[] location = {0, 0};
getLocationOnScreen(location);
rawX0 = event.getX(0) + location[0];
rawY0 = event.getY(0) + location[1];
float x = event.getRawX();
float y = event.getRawY();
Log.e(TAG + " ===", "actual raw co. " + x + "-" + y);
Log.e(TAG + " ===", "custom raw co. " + rawX0 + "-" + rawY0);
rawX1 = event.getX(1) + location[0];
rawY1 = event.getY(1) + location[1];
}
private float getRawX(MotionEvent event, int pointerIndex) {
float offset = event.getRawX() - event.getX();
return event.getX(pointerIndex) + offset;
}
private float getRawY(MotionEvent event, int pointerIndex) {
float offset = event.getRawY() - event.getY();
return event.getY(pointerIndex) + offset;
}
public void setInEdit(boolean isInEdit) {
this.isInEdit = isInEdit;
invalidate();
}
public void setOperationListener(OperationListener operationListener) {
this.operationListener = operationListener;
}
private float oldDist;
private final int NONE = -1;
private final int DRAG = 1;
private final int ZOOM = 2;
private int mode = NONE;
#Override
public boolean onTouch(View view, MotionEvent event) {
float downX, downY;
float moveX, moveY;
switch (event.getAction() & event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
savedMatrix.set(matrix);
start.set(downX, downY);
mode = DRAG;
Log.e(TAG + " ===", "Action down X=" + downX + " Y=" + downY);
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
savedMatrix.set(matrix);
midPoint(event);
mode = ZOOM;
Log.e(TAG + " ===", "Pointer down");
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
moveX = event.getX();
moveY = event.getY();
float mdX = moveX - start.x;
float mdY = moveY - start.y;
matrix.set(savedMatrix);
matrix.postTranslate(mdX, mdY);
invalidate();
Log.e(TAG + " ===", "draging");
Log.e(TAG + " ===", "draging x-y rawx-rawy " + event.getX() + "-" + event.getY() + " " + event.getRawX() + "-" + event.getRawY());
} else if (mode == ZOOM) {
float newDist = spacing(event);
float scale = (newDist / oldDist);
matrix.set(savedMatrix);
Log.e(TAG + " ====", "Zoom scale " + scale);
matrix.postScale(scale, scale/*, mid.x, mid.y*/);
invalidate();
Log.e(TAG + " ===", "scaling");
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.e(TAG + " ===", "Action up, Pointer up");
break;
}
if (operationListener != null) {
operationListener.onEdit(this);
}
return true;
}
public interface OperationListener {
void onEdit(VideoTextView videoTextview);
}
}
I have added my touch listener and all necessary functions that i have used to perform drag and scale event in my code to solve this issue, but every time i get fail to solve.
My Layout XML:
<FrameLayout
android:id="#+id/videoEditorParent"
android:layout_width="match_parent"
android:layout_height="400dp">
<RelativeLayout
android:id="#+id/vidEditorWrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#color/colorAccent">
<VideoView
android:id="#+id/vidEditor"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</FrameLayout>
can somebody help to solve this kind to problem?
Thanks.
public boolean onTouchEvent(MotionEvent event) {
//Log.e(Codistan_Tag, "Touch Event: " + MotionEvent.actionToString(event.getAction()));
if(isImageReady) {
if(isSelectionDragEnabled)
mPanListener.onTouchEvent(event);
if (isZoomEnabled) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
anchor_scale = mScaleFactor;
}
mScaleDetector.onTouchEvent(event);
mPanListener.onTouchEvent(event);
}
else {
switch (event.getAction()) {
case MotionEvent.ACTION_POINTER_3_DOWN:
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
break;
case MotionEvent.ACTION_POINTER_1_UP:
break;
case MotionEvent.ACTION_DOWN:
if (isSelectionToolEnabled)
isDrawFinished = false;
orig_x = event.getX();
orig_y = event.getY();
//Log.e(Codistan_Tag, "-------ORIGIN-------s: " + String.valueOf(orig_x) + " " + String.valueOf(orig_y));
orig_x = (orig_x - (dest.left));
orig_y = (orig_y - (dest.top));
if(java.lang.Math.round(mScaleFactor) > 2) {
orig_x += (scale_cur_x * (riz_scale));
orig_y += (scale_cur_y * (riz_scale));
} else {
orig_x += (scale_cur_x);
orig_y += (scale_cur_y);
}
orig_x /= java.lang.Math.round(mScaleFactor);
orig_y /= java.lang.Math.round(mScaleFactor);
orig_x *= scale;
orig_y *= scale;
//mSelectionTaskManager.setOrigin((int) orig_x, (int) orig_y);
if(isSelectionToolEnabled)
MovementStack.add(new Pair((int)orig_x, (int)orig_y));
Log.e(Codistan_Tag, "Codistan Origins: " + String.valueOf(orig_x) + ", " + String.valueOf(orig_y));
break;
case MotionEvent.ACTION_MOVE:
max_dist = dist * scale;
if (event.getAction() != 1) {
move_x = event.getX();
move_y = event.getY();
//Log.e(Codistan_Tag, "Move: " + String.valueOf(move_x) + ", " + String.valueOf(move_y));
move_x = (move_x - dest.left);
move_y = (move_y - dest.top);
if(java.lang.Math.round(mScaleFactor) > 2) {
move_x += (scale_cur_x * riz_scale);
move_y += (scale_cur_y * riz_scale);
} else {
move_x += (scale_cur_x);
move_y += (scale_cur_y);
}
move_x /= java.lang.Math.round(mScaleFactor);
move_y /= java.lang.Math.round(mScaleFactor);
move_x *= scale;
move_y *= scale;
Log.e(Codistan_Tag, "Codistan Move: " + String.valueOf(move_x) + ", " + String.valueOf(move_y));
if (move_x >= 0 && move_y >= 0) {
if (!isSelectionToolEnabled && isDistortionEnabled) {
warpPhotoFromC(image, height, width, max_dist/mScaleFactor, orig_x, orig_y, move_x, move_y);
first++;
distortedBmp.setPixels(image, 0, width, 0, 0, width, height);
fg = false;
} else {
//Cut Tool Enabled
distortedBmp.setPixels(image, 0, width, 0, 0, width, height);
MovementStack.add(new Pair((int) move_x, (int) move_y));
}
}
}
orig_x = move_x;
orig_y = move_y;
break;
case MotionEvent.ACTION_UP:
if (isSelectionToolEnabled)
isDrawFinished = true;
break;
}
}
v.invalidate();
}
return true;
}
basically m taking the screen shot and applying cropping on it i m selecting the cropping area using finger to draw a portion to crop . when i left moving my finger then the line appear but i want the line to follow my finger
Create a customView over which you can draw the line.As it appears that this view should appear above your image then better extend it with Framelayout with same .And place it above image.
FingerLine.class
public class FingerLine extends FrameLayout {
private final Paint mPaint;
private float startX;
private float startY;
private float endX;
private float endY;
public FingerLine(Context context) {
this(context, null);
}
public FingerLine(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.STROKE);
mPaint.setColor(Color.RED);
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(startX, startY, endX, endY, mPaint);
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
endX = event.getX();
endY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
endX = event.getX();
endY = event.getY();
invalidate();
break;
}
return true;
}
}
Note:Don't forget to call invalidate() because it will be responsible to call onDraw
I am trying to draw the line following by the users finger(touch). It is quite easy task to implement if there is no scaling.
Drawing without scaling works perfectly here is an screenshot
Works well. As you can see.
But if I scale an canvas it begins to draw points with some margin/measurement error/tolerance. It seems that I have not taken some value in advance while calculating scaled touch points, I have tried a lot of different formulas, but nothing helped.
Here is the result of zooming the canvas.
It seems that the problem in some delta value that I have to take into consideration
Because if I use this version of scale function it works well but scales only to the left top corner.
canvas.scale(mScaleFactor, mScaleFactor);
With this scaling
canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
Multitouch zoom (pinch) works well but coordinates are not correct.
Please help to solve the problem, it seems that I have to take these scalePointX, scalePointY variables when calculating scaled x and y.
Here is my code. Any help will be highly appreciated.
private void initWorkSpace(Context context) {
mPaint = new Paint();
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mRect = new Rect();
mPath = new Path();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(10f);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.getClipBounds(mRect);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
canvas.translate(mRect.top,mRect.left);
canvas.drawPath(mPath, mPaint);
canvas.restore();
}
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
}
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
public void clearCanvas() {
mPath.reset();
invalidate();
}
// when ACTION_UP stop touch
private void upTouch() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
Log.e("TOUCH","REAL X :" + ev.getX() + " REAL Y : " + ev.getY());
Log.e("TOUCH","RECT TOP :" + mRect.top + " RECT LEFT : " + mRect.left + " RECT RIGHT : " + mRect.right + " RECT BOTTOM :" + mRect.bottom);
final float scaledX = ev.getX()/mScaleFactor+mRect.left*mScaleFactor;
final float scaledY = ev.getY()/mScaleFactor+mRect.top*mScaleFactor;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
/*final float x = (ev.getX() - scalePointX) / mScaleFactor;
final float y = (ev.getY() - scalePointY) / mScaleFactor;
cX = x - mPosX + scalePointX; // canvas X
cY = y - mPosY + scalePointY; // canvas Y*/
// Remember where we started
mLastTouchX = scaledX;
mLastTouchY = scaledY;
Log.e("DOWN","Scale FACTOR : " + mScaleFactor);
Log.e("DOWN","X : " +mLastTouchX + " Y :" + mLastTouchY + " scalePointX : " + scalePointX + " scalePointY : " + scalePointY );
Log.e("DOWN","Last X : " + mLastTouchY + " Last Y :" + mLastTouchY);
startTouch(mLastTouchX, mLastTouchY);
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
/* final float x = (ev.getX() - scalePointX) / mScaleFactor;
final float y = (ev.getY() - scalePointY) / mScaleFactor;
cX = x - mPosX + scalePointX; // canvas X
cY = y - mPosY + scalePointY; // canvas Y
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX; // change in X
final float dy = y - mLastTouchY; // change in Y
mPosX += dx;
mPosY += dy;
invalidate();
}*/
Log.e("ACTION_MOVE","Scale FACTOR : " + mScaleFactor);
Log.e("ACTION_MOVE","X : " + scaledX + " Y :" + scaledY + " cX : " + cX + " cY : " + cY );
Log.e("ACTION_MOVE","Last X : " + mLastTouchX + " Last Y :" + mLastTouchY);
mLastTouchX = scaledX;
mLastTouchY = scaledY;
moveTouch(scaledX, scaledY);
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
mLastTouchX = 0;
mLastTouchY = 0;
upTouch();
invalidate();
}
}
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
scalePointX = detector.getFocusX();
scalePointY = detector.getFocusY();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
mScaleFactor = (mScaleFactor < 1 ? 1 : mScaleFactor);
invalidate();
return true;
}
}
You just need to convert the screen coordinates to the modified canvas coordinates:
Do these ways:
//If you have moved(transleted) the canvas:
TouchX = TouchX-translatedX;
TouchY=TouchY - translatedY;
// if you have scaled the canvas:
TouchX = TouchX/scaleFactor;
TouchY = TouchY/scaleFactor;
//if you have translated and scaled the canvas:
TouchX= (TouchX-translatedX)/scaleFactor;
TouchY = (TouchY-translatedY)/scaleFactor;
//And then draw with this TouchX and TouchY.
I hope this helps.
I need to make a arrow head in a line that is defined by a lot of points, that the user will drawn.
I hope that I could be clear about what is my question.
Thanks.
Note: All the questions/answers that I saw here were to resolve the problem of a line that was defined by two points, taken in the ACTION_DOWN and ACTION_UP. It's different in my case, because I need to take the first point while the line is being drawn.
This is my onTouch() method. It just draw a line defined by where the user touches in the screen.
public boolean onTouch(View v, MotionEvent event) {
if(getEditMode()) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
//Here i have to draw an arrow.
drawCanvas.drawPath(path, paint);
path.reset();
invalidate();
break;
}
invalidate();
return true;
} else {
return false;
}
}
I override draw and rotate the canvas before drawing the arrow.
//NOTE: 0, 0 is the bottom center point
vehicle.draw(canvas);
//draw arrow
if (arrow != null && heading != BusLocation.NO_HEADING)
{
//put the arrow in window
int arrowLeft = -(arrow.getIntrinsicWidth() / 4);
int arrowTop = -vehicle.getIntrinsicHeight() + arrowTopDiff;
//use integer division when possible. This code is frequently executed
int arrowWidth = (arrow.getIntrinsicWidth() * 6) / 10;
int arrowHeight = (arrow.getIntrinsicHeight() * 6) / 10;
int arrowRight = arrowLeft + arrowWidth;
int arrowBottom = arrowTop + arrowHeight;
arrow.setBounds(arrowLeft, arrowTop, arrowRight, arrowBottom);
canvas.save();
//set rotation pivot at the center of the arrow image
canvas.rotate(heading, arrowLeft + arrowWidth/2, arrowTop + arrowHeight / 2);
Rect rect = arrow.getBounds();
arrow.draw(canvas);
arrow.setBounds(rect);
canvas.restore();
}
}
So, I found a solution.
I store all the points that construct the line in an arraylist.
After I took a point of the line that would be in the 0.9 * arraylist.size() as reference to draw an arrowhead that follow the line direction.
Here is my onTouch() method and the funciont that I used to draw the arrow.
public boolean onTouch(View v, MotionEvent event) {
if(getEditMode()) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
path.moveTo(eventX, eventY);
pList.clear(); // When I start a line need to clear the previous coorfinates.
break;
}
case MotionEvent.ACTION_MOVE: {
int hSize = event.getHistorySize();
path.lineTo(eventX, eventY);
PointF aux, auxH;
if(darrow) {
if(hSize > 0) { // If movement is too fast.
for(int i = 0; i < hSize; i++) {
auxH = new PointF(event.getHistoricalX(i), event.getHistoricalY(i));
pList.add(auxH);
}
}
aux = new PointF(eventX, eventY);
pList.add(aux);
}
break;
}
case MotionEvent.ACTION_UP: {
pend.x = eventX;
pend.y = eventY;
if(darrow) { // If need to draw an arrow head to the end of the line;
arrowPath = drawArrow(pend); // Store the right arrowhead to a path.
}
drawCanvas.drawPath(path, paint);
drawCanvas.drawPath(arrowPath, paint);
path.reset();
arrowPath.reset();
invalidate();
break;
}
}
invalidate();
return true;
} else {
return false;
}
}
And the drawArrow(PointF) function:
private Path drawArrow(PointF pfinal) {
float dx, dy;
PointF p1, p2;
PointF pstart;
Path auxPath = new Path();
if(pList.size() > 0) {
PointF[] auxArray = pList.toArray(new PointF[pList.size()]);
int index = (int)(auxArray.length * 0.9);
Log.d(msg, "Size: " + auxArray.length + " | index: " + index);
pstart = auxArray[index];
dx = pfinal.x - pstart.x;
dy = pfinal.y - pstart.y;
float length = (float)Math.sqrt(dx * dx + dy * dy);
float unitDx = dx / length;
float unitDy = dy / length;
final int arrowSize = 10;
p1 = new PointF(
(float)(pfinal.x - unitDx * arrowSize - unitDy * arrowSize),
(float)(pfinal.y - unitDy * arrowSize + unitDx * arrowSize));
p2 = new PointF(
(float)(pfinal.x - unitDx * arrowSize + unitDy * arrowSize),
(float)(pfinal.y - unitDy * arrowSize - unitDx * arrowSize));
auxPath.moveTo(pfinal.x, pfinal.y);
auxPath.lineTo(p1.x, p1.y);
auxPath.moveTo(pfinal.x, pfinal.y);
auxPath.lineTo(p2.x, p2.y);
auxPath.close();
}
return auxPath;
}
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