Reputation: 1078
I am using canvas to make a simple drawing app. I am using onTouchEvent to handle touch event. I am facing a problem on vertical axis drawn point is differentfrom touched position. the vertical separation in between touched position and drawn position increases as I move upward. To make my problem more clear i am attaching screenshot of my app.
Blue line shows actual touched position and red drawn position.
Here is my code Mainactivity
public class MainActivity extends AppCompatActivity{
Path mPath;
Canvas canvas;
Paint paint;
float pointX;
float pointY;
int height;
RelativeLayout layout;
int layoutHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout=(RelativeLayout)findViewById(R.id.main_layout);
DisplayMetrics dp=getResources().getDisplayMetrics();
WindowManager windowManager=getWindowManager();
height=windowManager.getDefaultDisplay().getHeight();
int width =windowManager.getDefaultDisplay().getWidth();
Bitmap bg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
layout.setBackground(new BitmapDrawable(bg));
canvas=new Canvas(bg);
paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4);
mPath=new Path();
canvas.drawPath(mPath,paint);
canvas.drawBitmap(bg,0,0,paint);
}
public void clearCanvas(View v) {
mPath.reset();
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
layout.invalidate();
}
//override the onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
pointX = event.getX();
pointY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.v("TAG"," action down x:"+pointX+" y:"+pointY);
mPath.moveTo(pointX,pointY);
break;
case MotionEvent.ACTION_MOVE:
Log.v("TAG"," actionmove x:"+pointX+" y:"+pointY);
mPath.lineTo(pointX,pointY);
canvas.drawPath(mPath,paint);
break;
case MotionEvent.ACTION_UP:
break;
}
layout.invalidate();
return true;
}
}
xml layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.vikash.mydrawingapp.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="clear"
android:onClick="clearCanvas"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Upvotes: 1
Views: 1920
Reputation: 456
Use: event.getRawX()
Returns the original raw X coordinate of this event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views.
UPD: I just tried to repeat your app and all works correctly
activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.Test
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Test.java
public class Test extends View {
private Path path = new Path();
private Paint paint = new Paint();
{
paint.setColor(Color.GREEN);
paint.setStrokeWidth(4);
paint.setStyle(Paint.Style.STROKE);
}
public Test(Context context) {
super(context);
}
public Test(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Test(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public Test(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(event.getX(), event.getY());
break;
}
invalidate();
return true;
}
}
Upvotes: 4
Reputation: 762
Your problem is that your Canvas X-Axis has the same position of the Screen X-Axis, but your Canvas Y-Axis is offset from Screen Y-Axis (The "MyDrawingApp" bar sets that offset with its height).
What is happening is that when you "getY()" it returns the position of the touch taking as reference the entire screen not your canvas.
One solution is to get the position of the canvas on the screen and minus it to the "getY()" value. Doing this you will get a touch inside of your canvas.
I hope you will understand me, I am not English.
Greetings
Upvotes: 0