I'm trying to build a custom clock view in Android. See image http://twitpic.com/1devk7
So far to draw the time and hour markers I have been using the Canvas.rotate method to get the desired effect. However, notice that it is difficult to interpret the numbers in the lower half of the clock (e.g. 6 or 9?) because of the angle in which they are drawn.
When using drawText, is it possible to draw the text at 45/90/180 degrees so that all text appears upright when my onDraw method has finished?
To draw a text rotated by 90 degrees at point (x,y), use this code:
canvas.save();
canvas.rotate(-90, x, y);
canvas.drawText(text, x, y, paint);
canvas.restore();
How can you display upside down text with a textview in Android?
Related
I have took text on canvas applying rotation on it. Now I want to move the text horizontally but it's moving on cross. For rotation i have done something like below.
canvas.save();
canvas.rotate(-45,150,150);
canvas.drawText("Some Text", xAxis, 55, paint);
canvas.restore();
It's not moving straight because of the rotation applied to the whole canvas. Now I want this text to move horizontally straight line.
Is there any way around?
The output of the above code is like this
Right not if I increase the value of xAxis it's moving like the line red. I want it to move like line green in the picture.
In your code you rotated whole Canvas itself. Imagine you rotate your screen 45 degrees and move mouse horizontally - it will move with that rotation. You need another approach to rotate text, or you'll be needed to calculate move point depending on rotation angle (rotate point around point).
I've written a custom view that displays text in the center of the screen as seen below.
I've also made it so that if you touch the green box you can rotate and scale the text as seen below.
Heres the problem.
Whenever I rotate the text and let go, then try to rotate again it cant detect that the rect is being touched using myRect.contains(X,Y).
After some time I found that after its rotated, and touch where the original green box was, it allows me to rotate again.
OnTouchEvent is obviously calculating the Rects position correctly since it drawing in the correct location. I just can figure out why the touch coordinates seem to be referencing old positions.
Here's my onDraw() method.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.rotate((float)mAngle, mBorderRect.centerX(), mBorderRect.centerY());
canvas.drawRect(mBorderRect, mTextBorderPaint);
canvas.drawText(mText, mBorderRect.left, mBorderRect.bottom, mTextPaint);
canvas.drawRect(mResizeRect, mBGPaint);
canvas.restore();
}
Remember that you're rotating the canvas, not the Rect. To get this to work you'll have to apply the inverse rotation on the touch position first, then compute myRect.contains(X,Y).
Im making a 2d game where my character is controlled by a joystick and I rotate him using canvas.rotate(angel, x, y). My character shoots in the same direction he is heading, now I want to add fire coming out of his rifle when he shoots. The problem is, how do I rotate this fire-image around my character?
How I rotate My character:
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + charBitmap.getWidth() / 2, controls.charPosition.y + charBitmap.getHeight() / 2);
character.draw(canvas, controls.charPosition.x,controls.charPosition.y);
canvas.restore();
How I rotate the Fire:
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + (fireBitmap.getWidth()) / 2, controls.charPosition.y + (fireBitmap.getHeight() / 2));
fire.draw(canvas, controls.charPosition.x, controls.charPosition.y);
canvas.restore();
As you probably know, drawing my fire like this will make it rotate around its own center, just like with my character. But I want it to rotate around my character so it looks like the fire is coming out of his gun.
Any ideas? If anything is unclear please let me know in a comment. Thanks!
I will try to tailor this answer so that it's more specific, but if I understand you correctly, you may not want to rotate the canvas to create the rotation of the fire. Instead you may want to describe it with a trig function relative to the character's location. So I think it will look something like your drawing of the character.
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + charBitmap.getWidth() / 2, controls.charPosition.y + charBitmap.getHeight() / 2);
fire.draw(canvas, controls.charPosition.x+(fireRadius*cos(fireAngle)),controls.charPosition.y+(fireRadius*sin(fireAngle));
canvas.restore();
Where in this code, fireRadius is how far from the center of the character drawing you want the fire drawing to be and fireAngle is the angle of the fire from the center of the character. This won't be quite right because it will track the corner of the fire image, not the center. I think that can be fixed somewhat easily. If not, I will change soon.
You could use Canvas.translate(dx, dy). Idea is to move the fire a certain distance away from the gun, which can be directly along x -axis, and then rotate Canvas around gun center. This results fire to rotate given angle at given distance from the gun.
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + (fireBitmap.getWidth()) / 2, controls.charPosition.y + (fireBitmap.getHeight() / 2));
canvas.translate(distanceFromGun, 0);
fire.draw(canvas, controls.charPosition.x, controls.charPosition.y);
canvas.restore();
Please do note the order. Canvas matrix operations are pre multiplying and though translation is made later in the code.
An example can be found here compass.java.
Api here
Even when I first answered this question a few years ago, I didn't really understand how Canvas transforms (like translate, rotate, etc.) worked. I used to think that translate moved the thing that you were drawing. Actually, translate moves the entire coordinate system. This has the desired effect of also moving the thing you are drawing.
On your screen it looks like you are moving the drawing:
What is actually happening is you are moving the coordinate system to a new place on the canvas:
I draw the tree first at (0,0). Then I translate the origin of the coordinate system to some other spot on the canvas. Then I draw the tree again at (0,0). This way my drawing code doesn't have to change anything at all. Only the coordinate system changes.
Normally (0,0) is at the top left of your view. Doing Canvas.translate moves it to some other part of your view.
Saving and Restoring the Coordinate System
You can do save() and restore() to get back to your original coordinate system.
// draw the tree the first time
canvas.drawBitmap(tree, 0, 0, mPaint);
// draw the tree the second time
canvas.save();
canvas.translate(dx, dy); // dx = change in x, dy = change in y
canvas.drawBitmap(tree, 0, 0, mPaint); // draw still thinks it is at (0,0)
canvas.restore(); // undo the translate
When you restore, the drawing is already on the canvas. Restoring doesn't change that. It just moves the coordinate system back to wherever it was when you saved it.
Why Translate
Note that you could achieve the same affect by changing the x,y coordinates of the draw method:
// draw the tree the first time
canvas.drawBitmap(tree, x, y, mPaint);
// update the x,y coordinates
x += dx;
y += dy;
// draw the tree the second time
canvas.drawBitmap(tree, x, y, mPaint);
This might be more intuitive coming from a math background. However, when you are translating, rotating, and scaling your image, it is often much easy to keep your drawing logic the same and just transform the canvas. Recalculating x and y for every draw could be very expensive.
Imagine it's a Print Head.
The easiest way to explain this is to imagine it is the print head of an inkjet or 2D printer.
translate basically "moves" the print head along the X and Y axes the number of pixels that you tell it to.
The resulting position becomes the new "origin" (0,0).
Now that we understand that, let's make a simple face by doing the following:
Starting Origin:
x
The x will (roughly) represent where the origin (or print head) is.
Draw a rectangle for the left eye:
canvas.drawRect(10, 10, 10, 10, paint);
x__
|__|
Note: The "origin" has not changed, it is still at the top left of this rectangle.
Move "origin" right by 20 points:
canvas.translate(20, 0)
__ x
|__|
Draw the right eye using the exact same rectangle command:
canvas.drawRect(10, 10, 10, 10, paint);
__ x__
|__| |__|
Move "origin" back to the original X position and move it down on the Y axis:
canvas.translate(-20, 20) // Positive numbers for the second param is "down" on the y-axis.
__ __
|__| |__|
x
And draw a mouth to finish it off:
canvas.drawLine( 0, 0, 30, 0, paint );
__ __
|__| |__|
x___________
Now just move the "origin" down 20 points to showcase our masterpiece:
canvas.translate(0, 20)
__ __
|__| |__|
___________
x
Not perfectly to scale as there's only so much you can do with a monospace font. :)
Translate - Basically do what it says. Just translate the canvas using x,y. If you want to draw two objects and the one is just translation of the other e.g x2 = x1 + 50 for each point . You don't have to make all your calculations again for the second object but you can just translate the canvas and draw again the same object. I hope this example will help you.
it will change the position of your canvaz(except scale) either x or y
if we translate & scale then it is transformation in general terminology
When I call drawCircle (ex. canvas.drawCircle(x, y, r, mPaint);) and I use Paint Style STROKE to initialize the parameter mPaint, the result doesn't quite make a full 360 degrees (2*PI radian) circle in all cases. Sometimes you get a full circle (as I would expect) and sometimes only an arc.
Does someone have an idea what would cause this to happen ?
I don't know what cases work and which don't (yet). I've noticed the ones that don't work seem to be the larger circles I'm drawing (>100.0 radius). Could be size related. I am using floating point for x, y and r. I could try rounding to the nearest int when in the drawing code.
Are you doing anything else to the canvas before the drawCircle? This could happen if, for example you are scaling the canvas or transforming it before you draw the circle.