I am creating a application in which i want to draw the shape of touch event in my screen.Any ApI to get the shape of the touch event particularly?
Any examples or code snippets is greatly appreciated.
Thanks
Narayan
This code snippet should achieve what you want:
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawingView(this));
}
class DrawingView extends SurfaceView {
private final SurfaceHolder surfaceHolder;
private final Path path = new Path();
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public DrawingView(Context context) {
super(context);
surfaceHolder = getHolder();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setColor(Color.WHITE);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
if (surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas();
path.lineTo(event.getX(), event.getY());
canvas.drawPath(path, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
break;
}
return true;
}
}
}
Related
I'm trying to draw on surfaceview using onTouch listener, but i'm getting weird drawings (the edge of the line moves on it's own) as you can see in the GIF bellow:
Here's my code:
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Canvas canvas;
private Path path;
Paint mPaint = new Paint();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
surfaceView = (SurfaceView) findViewById( R.id.surfaceView );
surfaceHolder = surfaceView.getHolder();
surfaceView.getHolder().addCallback( this );
canvas = surfaceView.getHolder().lockCanvas();
mPaint = new Paint();
mPaint.setAntiAlias( true );
mPaint.setDither( true );
// mPaint.setColor(0xff000000);
mPaint.setStyle( Paint.Style.STROKE );
mPaint.setStrokeJoin( Paint.Join.ROUND);
mPaint.setStrokeCap( Paint.Cap.ROUND);
mPaint.setStrokeWidth( 50);
}
#SuppressLint("ClickableViewAccessibility")
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d( "surfaceCreated", "surfaceCreated " );
path = new Path();
surfaceHolder = holder;
surfaceView.setOnTouchListener( new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float X = event.getX();
float Y = event.getY();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
Log.d( "surfaceCreated", "action down x="+X );
// canvas = surfaceHolder.lockCanvas();
path.moveTo(X,Y);
// mv.touch_start(X,Y);
// canvas = surfaceHolder.lockCanvas();
break;
case MotionEvent.ACTION_MOVE:
Log.d( "surfaceCreated", "action move x="+X );
path.lineTo(X,Y);
break;
case MotionEvent.ACTION_UP:
Log.d( "surfaceCreated", "action up x="+X );
path.lineTo(event.getX(),event.getY());
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawPath(path, mPaint);
path.reset();
surfaceHolder.unlockCanvasAndPost(canvas);
// mCanvas.drawLine( downx, downy, upx, upy, mPaint );
break;
}
if(path != null){
Log.d( "surfaceCreated", "path is not null"+path );
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawPath(path, mPaint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
return true;
}
});
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
How i can solve the issue? and how i can make the surfaceview white, as you can see it's black at the beginning. Thank you!
Try the following:
1) Background Problem:
According to:
https://developer.android.com/reference/android/view/SurfaceView
The surface is Z ordered so that it is behind the window holding its
SurfaceView; the SurfaceView punches a hole in its window to allow its
surface to be displayed. The view hierarchy will take care of
correctly compositing with the Surface any siblings of the SurfaceView
that would normally appear on top of it. This can be used to place
overlays such as buttons on top of the Surface, though note however
that it can have an impact on performance since a full alpha-blended
composite will be performed each time the Surface changes.
and based on xav's answer: Set the Background Image of a SurfaceView
In order to change your surface background color, you can place a view (overlapping the surface view) on top of the surfaceView with a surfaceHolder pixel format of transparent.
2) Weird Drawing Problem: "the edge of the line moves on it's own"
You already got your answer: Thanks to Guillaume Adam
3) Example:
MainActivity.class
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private SurfaceView surfaceView;
private View surfaceBackground;
private Button b_change_surface_background_color;
private Button b_clear;
private Path path;
private Paint mPaint = new Paint();
private int[] colors = new int[]{Color.WHITE, Color.GREEN, Color.MAGENTA, Color.BLUE};
private int currentSurfaceBackgroundColor = Color.WHITE;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b_change_surface_background_color = (Button) findViewById(R.id.b_change_surface_background_color);
b_change_surface_background_color.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int colorIndex = new Random().nextInt(colors.length);
currentSurfaceBackgroundColor = colors[colorIndex];
changeSurfaceBackgroundColor(currentSurfaceBackgroundColor);
}
});
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.setZOrderOnTop(true);
surfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
surfaceView.getHolder().addCallback(this);
surfaceBackground = (View) findViewById(R.id.surfaceBackground);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(50);
}
#SuppressLint("ClickableViewAccessibility")
#Override
public void surfaceCreated(SurfaceHolder holder) {
path = new Path();
surfaceView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float X = event.getX();
float Y = event.getY();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
path.reset();
path.moveTo(X, Y);
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(X, Y);
break;
case MotionEvent.ACTION_UP:
path.lineTo(event.getX(),event.getY());
Canvas canvas1 = surfaceView.getHolder().lockCanvas();
canvas1.drawPath(path, mPaint);
surfaceView.getHolder().unlockCanvasAndPost(canvas1);
break;
}
if(path != null){
Canvas canvas = surfaceView.getHolder().lockCanvas();
canvas.drawPath(path, mPaint);
surfaceView.getHolder().unlockCanvasAndPost(canvas);
}
return true;
}
});
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
private void changeSurfaceBackgroundColor(#ColorInt int color) {
if (surfaceBackground != null) {
surfaceBackground.setBackgroundColor(color);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Change Surface Background Color"
android:textAllCaps="false"
android:layout_alignParentTop="true"
android:id="#+id/b_change_surface_background_color">
</Button>
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/b_change_surface_background_color"
android:id="#+id/surfaceView">
</SurfaceView>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/surfaceBackground"
android:layout_below="#id/b_change_surface_background_color"
android:background="#android:color/white">
</View>
</RelativeLayout>
4) Output
It may be because you reset the path before you synced the canvas with the surface view.
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawPath(path, mPaint);
path.reset(); // move this line out
surfaceHolder.unlockCanvasAndPost(canvas);
Try to move path.reset() just before path.moveTo(X,Y).
path.reset(); // add just above moveTo
path.moveTo(X,Y);
Surface view is actually behind your window. It punches a hole in the window for you to see it. So you can put things on top of it in your window, but nothing in your window can appear behind it. So background color won't work. But you get canvas with surface view so you can provide your own color to draw on canvas.
private void setRefreshColor(){
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
surfaceHolder.unlockCanvasAndPost(canvas);
}
Call this function from onSurfaceCreated(). Also every time you refresh canvas you need to draw REFRESH_COLOR.
I would like to add effects to my pointer. That is, while I am scrolling my finger in screen, show up effect or animation around which is showed up touched area. how to add?
I've found this:
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawingView(this));
}
class DrawingView extends SurfaceView {
private final SurfaceHolder surfaceHolder;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public DrawingView(Context context) {
super(context);
surfaceHolder = getHolder();
paint.setColor(Color.RED);
paint.setStyle(Style.FILL);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
if (surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawCircle(event.getX(), event.getY(), 50, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
return false;
}
}
}
I have made an app that plots a point on the image where I click. Now I want to add pinch zoom in and zoom out and drag functionality. What is the best way to do it?
Thanks in advance
This is my Main Activity
public class MainActivity extends ActionBarActivity {
private RelativeLayout rl_Main;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rl_Main = (RelativeLayout) findViewById(R.id.rl_main);
rl_Main.addView(new MyView(this));
}
class MyView extends View{
Paint paint = new Paint();
Point point = new Point();
public MyView(Context context) {
super(context);
paint.setColor(Color.RED);
paint.setStrokeWidth(15);
paint.setStyle(Style.STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
Bitmap b=BitmapFactory.decodeResource(getResources(), R.drawable.josepg);
canvas.drawBitmap(b, 0, 0, paint);
canvas.drawCircle(point.x, point.y, 1, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
point.x = event.getX();
point.y = event.getY();
}
invalidate();
return true;
}
}
class Point {
float x, y;
}
I'm making an app which paints a circle with a Touch event on the screen. The next code works fine:
Class Punto extends view{
Paint paint;
Point point = new Point();
Public Punto(Context contex){
super(context);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
paint.setColor(Color.BLUE);
canvas.drawCircle(point.x,point.y,10,paint);
}
#Override
public boolean onTouchEvent (MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
point.x = event.getX();
point.y = event.getY();
break;
}
return true;
}
class Point{
float x,y;
}
Activity:
public class Pintar extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Punto punto = new Punto(this);
setContentView(punto);
}
However I need that the circle be painted on a picture (in my case is a market's plane) but I don't know how I can do this.
Simply extend an ImageView:
class Punto extends ImageView {
I'm sorry, I assumed that the code you posted compiled...
Try this:
public class TouchImage extends ImageView {
Paint paint = new Paint();
Point point = new Point();
public TouchImage(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.BLUE);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(point.x, point.y, 10, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
point.x = event.getX();
point.y = event.getY();
invalidate();
}
return true;
}
class Point {
float x, y;
}
}
With a layout like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Use your reverse package name, for instance "example.com" is -->
<com.example.TouchImage
android:id="#+id/touchImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/map" />
</LinearLayout>
And an Activity that intercepts the coordinates when the TouchImage is touched:
public class Example extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TouchImage touchImage = (TouchImage) findViewById(R.id.touchImage);
touchImage.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Call the existing onTouchEvent() in TouchImage,
// if it draws a circle fetch the coordinates
if(v.onTouchEvent(event)) {
// Do something with event.getX(), event.getY()
}
return true;
}
});
}
}
Hi I am new in android also new in Stackoverflow.
I want create simple crop apps so I use the on image view and apply the on touch listener on this.when I touch on this. I draw simple and small default rect. After this when I drag the cursor on the screen I want to increase the size of rect in run time. So apply the attributes array on onDraw method.but I can`t do it. my code is below.
my Draw View Class
public class DrawView extends View
{
Paint paint ;
Canvas myCanvas;
float []atr;
public DrawView(Context context)
{
super(context);
}
public DrawView(Context context, float [] atr)
{
super(context);
this.atr=atr;
}
#Override
protected void onDraw(Canvas canvas)
{
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLUE);
canvas.drawRect(atr[0], atr[1], atr[2],atr[3], paint);
//System.err.println("After Call on Draw Method");
}
}
and i use in this class which my parent class.
enter code hereContext myContext;
RelativeLayout relMainLayout,relHeaderLayout,relBelowLayout;
DrawView drawView;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
myContext=DrawRectActivity.this;
LayoutInflater layoutInflater=(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int layoutId = myContext.getResources().getIdentifier("main","layout",getPackageName());
relMainLayout = (RelativeLayout) layoutInflater.inflate(layoutId,null);
relHeaderLayout=(RelativeLayout) relMainLayout.findViewById(R.id.relHeaderLayout);
relBelowLayout=(RelativeLayout) relMainLayout.findViewById(R.id.relBelowLayout);
/*int[] atr={10,10,00,00};
drawView=new DrawView(myContext,atr);
drawView.bringToFront();
drawView.setBackgroundColor(Color.YELLOW);
RelativeLayout.LayoutParams drawParams=new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,200);
drawParams.addRule(RelativeLayout.BELOW, relHeaderLayout.getId());
relMainLayout.addView(drawView, drawParams); */
setContentView(relMainLayout);
//drawView.setOnTouchListener(this);
//relMainLayout.setOnTouchListener(this);
}
public boolean onTouch(View v, MotionEvent event)
{
float x,y;
float incx=5,incy=5;
x=event.getX();
y=event.getY();
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
System.err.println("X-->"+x);
System.err.println("Y-->"+y);
float[] atr={x,y,x+incx,y+incy};
drawView=new DrawView(myContext,atr);
drawView.bringToFront();
//drawView.setBackgroundColor(Color.YELLOW);
RelativeLayout.LayoutParams drawParams=new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,200);
drawParams.addRule(RelativeLayout.BELOW, relHeaderLayout.getId());
relMainLayout.addView(drawView, drawParams);
break;
case MotionEvent.ACTION_MOVE:
float x1=event.getX();
float y1=event.getY();
incx=x1+incx;
incy=y1+incy;
float[] at1={x,y,incx,incy};
drawView=new DrawView(myContext,at1);
drawView.bringToFront();
break;
case MotionEvent.ACTION_UP:
System.err.println("Up X-->"+x);
System.err.println("Up y-->"+y);
System.err.println("Up X-->"+incx);
System.err.println("Up y-->"+incy);
break;
default:
break;
}
/*int[] atr={100,100,00,00};
DrawView drawView2=new DrawView(myContext, atr);
Bitmap myCanvasBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas myCanvas = new Canvas();
myCanvas.setBitmap(myCanvasBitmap);
//canvas.setDensity(BIND_AUTO_CREATE);
drawView2.draw(myCanvas); */
return false;
}
and also use the touch event on this.