in my application on touch event i want to drawrectangle-i tried this.butnot getting exactly how to draw.please help me.
i want to draw rectangle on points where is touched.
how can i use getX() and getY() in drawRect() method?
below is code-
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN) {
int X=event.getX(); int Y=event.getY();
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(getResources().getColor(R.color.Yellow)) ;
paint.setAlpha(opacity);
Canvas canvas1 = new Canvas(mutableimage1);
canvas1.drawRect(2.5f,2.5f,2.5f,2.5f, paint);
}
}
Don't instantiate a new object in the onTouch method : canvas1 = new Canvas(...)
It will cause freezes and lags. Create this canvas once for good at the creation of your view.
Be carefull I think your drawRect() call won't draw what you need :
you are drawing a rect with x=2.5 y = 2.5 width=2.5 height=2.5
I assume you need to position your rect according to the touch position :
//set the x and y pos according to the touch point
// by removing half the size of the rect we center it on this point ;)
canvas1.drawRect( X-1.25f, Y-1.25f, 2.5F, 2.5f, paint );
Otherwise that's quite correct, but be aware that you are drawing on a mutable bitmap ("mutableimage1") that won't necessary be displayed.
You probably want to add the display in the onDraw(Canvas viewCanvas) method of your view.
using :
viewCanvas.drawBitmap(mutableimage1, 0,0, aPreviouslyCreatedPaint);
Related
I am developing an application for technical drawing and I need to add a few tools to draw lines, circles, rectangles and corners. Now I can draw lines and free hand drawing but I cannot draw circles, rectangles and corners. I found in lot of websites how to draw it but static, I mean, draw the shape in the position you pre-set or the position where you touch but I need to know how to draw, for example, a circle in the position I touch and make it bigger than I separate my fingers. I hope you understand what I mean.
You can have two variables x and y, then every time you touch the screen set x and y to that value, while drawing draw the circle with coordinates x and y.
If you are drawing and you just want to keep a painted circle, you can paint the circle and add it inside your canvas on x and y, then the next time you touch the screen a new circle will be painted on x and y and the old one will remain painted.
Are you using Canvas ? if so you can find out how to do this here (Canvas documentation) and here (Bitmap documentation). Depending on your situation you can create a new Bitmap and assign it to Canvas then draw on the Canvasand inside your bitmap you will have your desired circles and other shapes, on the next drawing frame, draw new shapes and the changes will remain.
Edit: In order to have dynamic radius follow this logic, when you touch the screen, set x and y to that point (the center of the circle), while moving the finger on the screen, calculate the radius comparing to x and y, when lifting your finger apply the drawing on the bitmap as told above.
Some code:
public boolean onTouchEvent(MotionEvent e)
{
switch (e.getAction())
{
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
//If I'm not wrong this is how to calculate radius,
//I'm at work and can't test this now, you can use your way
int distanceX = (int) event.getX() -x;
int distanceY = (int) event.getY() -y;
radius = sqrt(distanceX *distanceX + distanceY *distanceY);
break;
case MotionEvent.ACTION_UP:
//Draw circle inside your bitmap here
//This is like a flag to notify the program that no new shape is being drawn
x = -1;
break;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(myBitmap, 0, 0, null);
//A new shape is being drawn
if (x != -1)
//In here you place a switch to decide which shape you are drawing
//for this example i assume circle
canvas.drawCircle(radius, x, y, paint);
}
When you are lifting your finger the new circle should be painted on your bitmap so you don't have to add extra code for each new circle.
Edit2: I will add more code with the Bitmap and Canvas method i described.
Bitmap myBitmap;
Canvas myCanvas;
//Constructor
public myActivity(Bundle bundle) //or whatever your constructor is
{
myBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
myCanvas = new Canvas(myBitmap);
}
Now anything you draw on "myCanvas" will be applied to "myBitmap", when ACTION_UP activates draw circle on "myCanvas" which is drawn on the draw function.
case MotionEvent.ACTION_UP:
myCanvas.drawCircle(radius, x, y, paint);
x = -1;
break;
I'm performing a very small test to debug something larger, and am having trouble figuring out what's causing this issue.
I have an ImageView, a Canvas and a Bitmap. I initialize the ImageView and set it to the Bitmap, and then set the Canvas to the bitmap, as such:
_image.setImageBitmap(bitmap);
Canvas canvas = new Canvas(bitmap);
I then attach an onTouchListener to _image and listen for MotionEvent.ACTION_UP to be detected. At that point I draw a Rect on the Canvas, as such:
Rect rect = new Rect((int)event.getX(),event.getY(),event.getX()+20,event.getY()+20);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(rect,paint);
I've tried this with bitmap images of different sizes, to smaller than the full display, to very nearly the exact size, to larger, and I can never get the Rect to draw right where my finger touches the screen. I've tried different conversions on getX(), attempting to convert to dp, from dp, used getRawX/Y() instead; basically a bunch of different solutions, none of which have worked. I've tried getting the ratio of the bitmap's size to the screen size and multiplying/dividing by that; nothing has been able to solve this very simple issue.
Quite possibly I've tried the right approach at some point and simply implemented it incorrectly. I'd really appreciate some advice on what's causing the Rect to draw where it is, what conversion is needed to get it to draw right where the touch occurs, and why. The 'why' is because I want to learn from this.
Edit: This is an approximation of what happens. The red rectangle is where the actual touch occurs, and the blue is where it is drawn. It scales the further from X=Y=0 you get. Also, I just noticed that it also scales depending on the width and height of the image you're using.
So, I believe I've figured out the math which allows me to transform the onTouch coordinates onto the Canvas.
The reason I really wanted to go this route (as opposed to a custom subclass for ImageView) is because I'm not really that interested in the drawing of the rectangles: I'm more interested in accurately mapping onTouch coordinates onto specific OCRed text strings in the bitmap. The reason I was performing this exercise was to figure out why the touches weren't being attributed to the correct lines of text, and I was using drawn Rects to estimate where the touches were being recorded.
So, on to the math, which turned out to be a lot simpler than I'd feared:
int x1 = (int)(event.getX() * ((float) canvas.getWidth() / _image.getRight()));
int y1 = (int)(event.getY() * ((float) canvas.getHeight() / _image.getBottom()));
I multiply the onTouch coordinates by the ratio of the Canvas's dimensions to the ImageView's dimensions, which I cast to a float. Painting this as follows:
rect = new Rect(x1-10,y1-10,x1+10,y1+10);
//I took the advice about centering the Rect around the touch for clarity
paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(rect,paint);
And the Rect is exactly where the touch was, regardless of bitmap size.
I found it interesting that it didn't cause any problems that I had called
_image.setAdjustViewBounds(true);
earlier in my program, which I did in order to remove some padding from the bitmap (which was showing up for some reason, possible due to the scaling). Also interesting is the fact that the ImageView is contained in a ScrollLayout, but even if the image is large enough to scroll though, it doesn't seem to need to take the scroll displacement into account.
Thanks to kcoppock for taking the time to help me out, and to the other user (whose comment was deleted when he realized he had misunderstood me) for taking the time as well.
I'd imagine your actual Bitmap is larger than the View and is scaled down. Since you're drawing in the coordinates of your bitmap, and that bitmap is being scaled down, the location will also be scaled down to match.
What you more likely want to do is make a subclass of ImageView, and then draw the Rect in onDraw() based on the location received in onTouchEvent(). Alternatively, you could do some math to figure out how much the bitmap is being scaled down relative to the view size, and scale up your coordinates by the inverse. A quick implementation of this touchable ImageView would be something like this:
public class DrawableImageView extends ImageView {
private final int mRectSize;
private final Paint mPaint;
private final Rect mRect = new Rect();
public DrawableImageView(Context context) {
super(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mRectSize = (int) (getResources().getDisplayMetrics().density * 20);
}
// Other constructors omitted for brevity
#Override public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
final int x = (int) event.getX();
final int y = (int) event.getY();
mRect.set(x, y, x + mRectSize, y + mRectSize);
mRect.offset(-(mRectSize / 2), -(mRectSize / 2));
invalidate();
return true;
} else {
return super.onTouchEvent(event);
}
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(mRect, mPaint);
}
}
I want to move a bitmap image along consecutive coordinates in SurfaceView. I have a bitmap myBall drawn in the coordinate (x1, y1) on a SurfaceView as follows (partial code)(
public class MainSurfaceView extends SurfaceView implements Runnable {...
...
#Override
public void run() {
while (isRunning) {
if (!myHolder.getSurface().isValid())
continue;
Canvas canvas;// Define canvas to paint on it
canvas = myHolder.lockCanvas();
//Draw full screen rectangle to hold the floor map.
Rect dest = new Rect(0, 0, getWidth(), getHeight());
Paint paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(bgImage, null, dest, paint);
//This is the ball I want to move
canvas.drawBitmap(myBall, x1, y1, null);
myHolder.unlockCanvasAndPost(canvas);
}
}
Now I want to move it to (x2, y2) then (x3, y3) and ... as many as needed and one after the other. I have tried to use TranslateAnimation but couldn't do it.
I have figured out how to animate using a coordinates. I will explain what I did hopping that it will be helpful to others:
First I saved the coordinates as Point object
List<Point> point_list = new ArrayList<Point>();
point_list.add(new Point(x_value, y_value));//Add the x and y coordinates to the Point\
Leave implementing Runnable and use onDraw() method instead of run() method as follows:
public class MainSurfaceView extends SurfaceView {...
....
#Override
protected void onDraw(Canvas canvas) {
// Draw full screen rectangle to hold the floor map.
Rect fArea = new Rect(0, 0, getWidth(), getHeight());
Paint paint = new Paint();
paint.setFilterBitmap(true);
// draw the paint on the rectangle with the floor map
canvas.drawBitmap(bgImage, null, fArea, paint);
// Get the coordinates of x & y as Point object
List<Point> myPoints = point_list;
// Start printing myBall on the floor (view)
try {
if (index < myPoints.size()) {
// Increment the value of index and use it as index for the point_list
index++;
}
// Print myBall in each coordinates of x & y using the index
canvas.drawBitmap(myBall, myPoints.get(index).x, myPoints.get(index).y, null);
} catch (IndexOutOfBoundsException e) {
// TODO: handle exception
}
}
I use try and catch to avoid IndexOutOfBoundryExeption
Cheers!
I think this might be what you're after. What you're trying to do is tween the bitmap and there are a few ways you can do that. There is also the ViewPropertyAnimator, which can animate an entire view.
I am learning android Live wallpaper development. I found an awesome template in the AndEngine Forums
In this template I found an overridable method OnTab which provides 2 parameters i.e x coordintate & y coordinate .
protected void onTap(final int pX, final int pY)
{
SurfaceHolder holder= //Get current surface holder object
Paint paint = new Paint();
Canvas canvas= holder.lockCanvas();
paint.setColor(Color.WHITE);
canvas.drawCircle(20, 50, 25, paint);
}
I want to draw a circle when user tabs or touches the screen but i am finding it difficult to get the sufaceholder object which will let me draw a circle on the canvas Or can i achieve this some other way?
You need to do the drawing within the onDraw() method. When a touch is occurring you should save the X and Y location and then in the onDraw() method draw the circle.
I am trying to redraw an image on the canvas on an onTouch event. I am able to draw the image on the canvas, but I want the image to redraw at a particular x,y.
protected void onDraw(Canvas canvas)
{
mBitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.ab);
mBitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.ab);
this.canvas=canvas;
Paint p = new Paint();
p.setColor(Color.parseColor("#FFFFFF"));
canvas.drawLine(x1, y1, x2 , y2, p);
canvas.drawBitmap(mBitmap1, 70, 60, null);
canvas.drawBitmap(mBitmap1, 185, 60, null);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
final int x=(int)event.getX();
Log.i("***********xPos","="+x);
final int y=(int)event.getY();
Log.i("***********yPos","="+y);
if(event.getAction()==MotionEvent.ACTION_UP)
{
}
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
canvas.drawBitmap(mBitmap1,50+x,60,null );
this.postInvalidate();
}
if(event.getAction()==MotionEvent.ACTION_MOVE)
{
}
return false;
}
I think I understand your problem. You are calling postinvalidate() method each time when action.down is called, so it calls ultimately call ondraw(). So it will redraw it on bitmap for particular setted value at which you put in ondraw again.
So you looks that it remain unchanged.
Follow these steps:
use some public variables for drawing bitmaps in ondraw method for x and y axis, lets say initx and inity
then on touch event:update this value by adding your x and y value to initx and inity resp.
like:initx=initx+x;
inity=inity+y;
And last in cation down event just call post.invalidate or ondraw method.
See the MotionEvent class that provides the coordinates of where the user touched the screen.