I am unable to get the canvas object in ontouch().Without the canvas I cannot draw a circle when touched.How can I draw any shape or image when touched
public class Board extends View implements View.OnTouchListener {
public Board(Context context) {
super(context);
Paint paint1 = new Paint();
paint1.setTextSize(50);
paint1.setColor(Color.WHITE);
View view=this;
view.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(200, 100, 0);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
final int action = MotionEventCompat.getActionMasked(event);
int pointer = MotionEventCompat.getActionIndex(event);
if (action == MotionEvent.ACTION_DOWN) {
canvas.drawCircle(70, 1100, 50, paint1);
}
return false;
}
To draw on canvas wherever you touch, you need a path to keep track of your touch points and path. Using the path object you can draw on canvas. See this answer Draw on touch
Related
I have a custom surfaceView which will paint the surface based on Touch event. When i draw something on this view it is working fine. But when i tried to erase the paint, nothing got erased. Please find the sample code snippet below:
public class MySurfaceView extends SurfaceView {
private static final String TAG = "FreeHandDrawing";
public static Canvas mCanvas;
SurfaceHolder holder;
private static Path path;
private Paint paint;
private ArrayList<Path> pathArrayList = new ArrayList<>();
private boolean freeHandMode;
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
freeHandMode = false;
path = new Path();
holder = getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
setDrawingCacheEnabled(true);
this.setZOrderOnTop(true);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(0xFF22FF11);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(8);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(freeHandMode) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.d("Action", "Placed");
path.moveTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
Log.d("Action", "Moved");
path.lineTo(event.getX(), event.getY());
pathArrayList.add(path);
}
mCanvas = holder.lockCanvas();
if (mCanvas != null) {
if (pathArrayList.size() > 0) {
mCanvas.drawPath(pathArrayList.get(pathArrayList.size() - 1), paint);
}
holder.unlockCanvasAndPost(mCanvas);
} else {
Log.d(TAG, "Canvas is NULL");
}
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d(TAG, "On draw called");
}
public void eraseDrawing() {
pathArrayList.clear();
invalidate();
}
public void drawEnableDisable(boolean mode) {
freeHandMode = mode;
}
}
What is the problem with the code above ?
You should keep your drawing code in the onDraw method
#Override
protected void onDraw(Canvas canvas) {
// In case you want to delete/erase when path array/list is cleared.
if (pathArrayList.size() == 0) {
canvas.drawColor(0, Mode.CLEAR);
}
// In case, you want to draw all paths also in onDraw
for(Path path : pathArrayList) {
canvas.drawPath(path, paint);
}
}
When you clear the Path Array(list) and then upon calling invalidate(), onDraw gets triggered.
Note: You're supposed to call invalidate() at the end of onTouchEvent() to tell the system to update the screen. Calling invalidate() will get the framework to eventually call onDraw().
Also you should NOT use canvas obtained by lockCanvas as it will not be hardware accelerated. Instead you should use the canvas passed as an argument to onDraw() itself.
You can choose to make the system a bit smart by not having to draw the pull list of paths every frame and instead handle erases/redraws etc by using special flags. And otherwise just render the latest path generated by the most recent call to onTouchEvent().
I have extended View to use canvas. I have draw basic drawings in onDraw() method, when user touches in the canvas I have to draw an image there, for that I have used canvas inside onTouchEvent() method,it is not drawing anything there, the code is given below, what is the problem and how can i resolve this
public class ScreenView extends View(){
static Canvas canvas;
Bitmap bm;
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
bm = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
canvas.draw.......
......
...........
}
public boolean onTouchEvent(final MotionEvent event) {
handleTouches(event.getX(), event.getY());
return false;
}
public void handleTouches(float x, float y) {
xLocTouch = (int) x;
yLocTouched = (int) y;
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawBitmap(bm, xLocTouch ,yLocTouched , paint);
}
}
You should call invalidate() method inside onTouchEvent, then your onDraw() method will be called, and you just should store your x and y coordinates, and then draw bitmap to this coordinates, like this:
public class ScreenView extends View {
int xLocTouched;
int yLocTouched;
Bitmap bm;
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
bm = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
//your basic drawings also should depends on xLocTouched and yLocTouched.
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawBitmap(bm, xLocTouched ,yLocTouched , paint);
}
public boolean onTouchEvent(final MotionEvent event) {
xLocTouched = (int) event.getX();
yLocTouched = (int) event.getY();
invalidate();
return false;
}
}
I am trying to implement a Drawing Application in Android. Where the user should be able to select and move the drawn shapes.
Currently i have statically drawn some rects and text on my Drawing Canvas:
View mDrawingCanvas = new View(mContext)
{
ShapeDrawable rectangle;
#Override
public boolean isFocused() {
// TODO Auto-generated method stub
Log.d(TAG, "View's On focused is called !");
return super.isFocused();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return super.onTouchEvent(event);
}
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
// Work out current total scale factor
// from source to view
final float scale = mSourceScale*(float)getWidth()/(float)mSize.x;
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
//Custom View
rectangle = new ShapeDrawable(new RectShape());
rectangle.getPaint().setColor(Color.GRAY);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
rectangle.setBounds((int)(50*scale), (int)(30*scale), (int)(200*scale), (int)(150*scale));
rectangle.draw(canvas);
rectangle.getPaint().setColor(Color.BLUE);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
rectangle.setBounds((int)(200*scale), (int)(200*scale), (int)(400*scale), (int)(350*scale));
rectangle.draw(canvas);
}
};
I want to select (draw borders on the selected shape) and move the drawn Shapes in onTouch events of the drawing canvas.
Can some one please guide me about this, any help is Highly Appreciated.
This answer has demonstrated the Shape Moving Methodology that i was looking for.
And my problem is solved now. The Link is :
Drag and move a circle drawn on canvas
You should save the X and Y positions in the touch event and use them when drawing your shapes.
Below is a very basic example of how to do this, but you need to improve it (check if the touch is inside the object and only change values for that object)
Example:
public class DrawTest extends View {
private static final String TAG = "Desenho";
private ShapeDrawable rectangle;
private Paint paint;
private float currX, currY;
private Rect blue, gray;
public DrawTest(Context context) {
super(context);
currX = 1;
currY = 1;
gray = new Rect(50,30,200,150);
blue = new Rect(200,200,400,350);
paint = new Paint();
rectangle = new ShapeDrawable(new RectShape());
}
#Override
public boolean isFocused() {
Log.d(TAG, "View's On focused is called !");
return super.isFocused();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
currX = event.getX();
currY = event.getY();
invalidate();
Log.d(TAG, "View's On touch is called! X= "+currX + ", Y= "+currY);
return super.onTouchEvent(event);
}
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
//Custom View
rectangle.getPaint().setColor(Color.GRAY);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
gray.set((int)(50+currX), (int)(30+currY), (int)(200+currX), (int)(150+currY));
rectangle.setBounds(gray);
gray = rectangle.getBounds();
rectangle.draw(canvas);
rectangle.getPaint().setColor(Color.BLUE);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
blue.set((int)(200+currX), (int)(200+currY), (int)(400+currX), (int)(350+currY));
rectangle.setBounds(blue);
blue = rectangle.getBounds();
rectangle.draw(canvas);
}
}
Im developing an application which having Images as a Index on selection of particular image that activity will begin but I dont know how to set onClickListener or onTouchListener in Canvas heres my code
public class DrawView extends View implements OnTouchListener {
LinearLayout mLayout;
Bitmap index;
Bitmap book;
Bitmap bird;
Bitmap game;
Bitmap mail;
Bitmap music;
Bitmap torch;
Paint paint;
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
index = BitmapFactory.decodeResource(getResources(), R.drawable.photo1);
book = BitmapFactory.decodeResource(getResources(), R.drawable.book);
game = BitmapFactory.decodeResource(getResources(), R.drawable.game);
music = BitmapFactory.decodeResource(getResources(), R.drawable.music);
}
public void onDraw(Canvas canvas){
paint = new Paint();
Bitmap indexcanvas = Bitmap.createScaledBitmap(index, canvas.getWidth(),
canvas.getHeight(), true);
canvas.drawBitmap(indexcanvas, 0, 0, paint);
canvas.drawBitmap(book, 160, 100, paint);
canvas.drawBitmap(game, 30, 10, paint);
canvas.drawBitmap(music, 80, 50, paint);
}
public boolean onTouch(View v, MotionEvent event) {
return false;
}
Please if anyone knows how to add onClickListener for particular image e.g. here if I click on Book then bookActivity will start.
try something like this:
public boolean onTouch(View v, MotionEvent event) {
if((event.getX(0)>=160) &&
(event.getY(0)>=100) &&
( event.getX(0)<=160+BOOK_IMG_WIDTH) &&
(event.getY(0)<=100+BOOK_IMG_HEIGHT))
{
//book selected
}
return true;
}
Use ImageView instead of bitmap and add it to your layout:
book = new ImageView(context);
book.setImageResource(R.drawable.book);
book.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
/*...*/
}
};);
Save the images' coords in an ArrayList. Set OnClickListener on the context, get the point coords that has been clicked, find the image in the arraylist and do something :)
i have a bitmap inside a canvas.the class implements ontouchlistener.i need to hide the image while touch on the image.
class Panel extends View implements View.OnTouchListener {
Paint linepaint=new Paint();
public Panel(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
Bitmap imgtable = BitmapFactory.decodeResource(getResources(), R.drawable.table_01);
canvas.drawBitmap(imgtable, centrex, centrey, null);
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}
Make on touch listener for the view where you draw the image. And there change the visibility of the view. Not in onDraw();
Edit:
If you set the Bitmap image for example on a ImageView, then onTouchListener() must be applied on the ImageView. Bitmap image is only a data that is supplied to the view(s).