Is it possible to rotate an ImageButton using the onCreate() function? Or do you have to use an Animation which starts onCreate()? Because with an Animation i can see a little "flick" on Activity start...
you can use ViewCompat.setRotation(buttonInstance, rotationAngle);. From the documentation
Sets the degrees that the view is rotated around the pivot point.
You can override the onDraw() method using a custom class that extends ImageButton (which I'm sure you have).
#Override
protected void onDraw(#NonNull Canvas canvas) {
super.onDraw(canvas);
// Rotate a Bitmap
final Matrix matrix = new Matrix();
matrix.setRotate(angle, imageCenterX, imageCenterY);
canvas.drawBitmap(bitmap, matrix, null);
/*
* OR
**/
// Rotate the canvas
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(-angle);
canvas.drawBitmap(bitmap, left, top, null);
canvas.restore();
}
Choose one or the other solution, not both together ;)
EDIT
After some quick reflection, that could also work (not tested):
#Override
protected void onDraw(#NonNull Canvas canvas) {
canvas.rotate(-angle);
super.onDraw(canvas);
}
Related
I have a custom view extends form TextView,and write some code in onDraw():
#Override
protected void onDraw(Canvas canvas) {
if (mTextShader == null) {
createShader();
}
shaderMatrix.setTranslate(mProgressWidth,0);
mTextShader.setLocalMatrix(shaderMatrix);
Paint paint = new Paint();
paint.setShader(mBgShader);
canvas.drawRect(0,0,mProgressWidth,getBottom(),paint);
getPaint().setShader(mTextShader);
super.onDraw(canvas);
}
It looks like this:
enter image description here
Just set some shader,and draw a rect,it works fine if I don't use
android:gravity="center"
and
android:singleLine="true"
together,(just one of them is pretty good,)
if only use this property,these shaders and rect are gone!
why?
Before you draw in the canvas, translate the scrolled XY distance
canvas.translate(getScrollX(), getScrollY());
canvas.drawRect(0,0, getWidth(), getHeight(), borderPaint);
your super.onDraw(canvas); should be first line otherwise parent will paint on top of your drawing. also call this setWillNotDraw(false) in your constructor.
I hava a customized view and I draw its UI on its onDraw(Canvas canvas) method. I some case I need do some animation (anim is true)
public class GameView extends View {
//more code
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(item.getBitmap(), item.getXY().getX(), item.getXY().getY(), null);
canvas.drawBitmap(ResizedBitmapMapping.getHouse(), 0f, 0f, null);
if(amin){
canvas.save();
canvas.rotate(currentValue);
drawBall(canvas);
canvas.restore();
}
}
But the ball is very small, so only a small part of the view needs to be re-drawn. it should be a performance issue to draw the whole view. What is the right to draw such animation?
What your are looking for is Canvas.clipRect().
Here is a short video from Google that explains how it works and how to use it. Alternatively, you can invalidate only a region of a view with View.invalidate(int,int,int,int).
In my OnDraw method, I draw path into my canvas (circle with segements). All work well, now what I am not sure how to do is how can I tilt it (sort of rotation around one axis).
Basically, what I am trying to achieve is something like the tilt functionality of google map.
Here is the pseduo code:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// I do all the drawing here
canvas.tilt(45degrees) <-----??
}
I don't think you have to create the tilt effect within the onDraw method modifying your canvas manually. Instead use setRotationX() method on the whole View. You can also define it in xml as android:rotationX="45".
Use Canvas.concat(Matrix) with a rotation matrix, i.e.:
class MyView {
private final Matrix rotate = new Matrix();
public MyView()
{
rotate.setRotate(45.0f);
}
protected void onDraw(Canvas c)
{
super.onDraw(canvas);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.concat(rotate);
canvas.restore();
}
}
Note also that you should not do any memory allocations inside onDraw() as per the android linter.
I'm extending LinearLayout:
public class MyLinearLayout extends LinearLayout {
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(0xFFFF0000);
canvas.drawLine(0, 0, getWidth(), getHeight(), paint);
}
}
If the layout has child elements, shouldn't the red line above be drawn on top of them? Considering a layout like:
<MyLinearLayout>
<ImageView />
</MyLinearLayout>
I'd expect to get the red line drawn above the child ImageView. But it gets drawn below it. I was assuming all child drawing would have been completed after the super.onDraw() line is finished.
Is there a way to get to the canvas and draw something on it after all child drawing has been completed?
Thanks
Layouts don't draw unless you call setWillNotDraw(false);. They do that for efficiency reasons.
EDIT:
onDraw() really is meant to just allow you to modify the Canvas before the drawing operation happens. It doesn't actually draw. What you want to do is override draw() like so:
#Override
protected void draw(Canvas canvas) {
super.draw(canvas);
Paint paint = new Paint();
paint.setColor(0xFFFF0000);
canvas.drawLine(0, 0, getWidth(), getHeight(), paint);
}
Calling the super will draw all the children in the view. Then it will draw all the lines. I do still believe you need setWillNotDraw(false) to be called though.
I'm rewriting my answer as I hadn't seen your line of code where you were drawing to the canvas.
The canvas like some other graphics environments is inverted. So calling getHeight() is actually drawing the line at the bottom. Instead call
canvas.drawLine( 0, 0, getWidth(), 0, paint);
This means draw the line at the top, across the width of the view.
Also, calling super first paints the children prior to any custom painting so your fine there.
If you have a LinearLayout and you need:
draw all of its children first, like buttons, image views
then, on top of those components, draw something directly on the canvas.
You can try this:
public class YourClass extends LinearLayout
{
#Override
protected void dispatchDraw(Canvas canvas)
{
super.dispatchDraw(canvas);
// do your custom drawings afterwards
canvas.drawCircle...
canvas.drawLine...
Okay, so I'm trying to draw to a canvas on Android from outside of the onDraw method.
It's just easiest to show my code:
public class TestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Paint p = new Paint();
p.setColor(Color.GREEN);
Panel a = new Panel(this,150,150,50,p);
a.drawThing();
setContentView(a);
}
class Panel extends View{
private float radius, x, y;
private Canvas CAN;
private Paint p;
public Panel(Context context, float x, float y, float radius, Paint p){
super(context);
this.x = x;
this.y = y;
this.radius = radius;
this.p = p;
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
CAN = canvas;
}
public void drawThing(){
CAN.drawCircle(x, y, radius, p);
}
}
}
Do you see what I'm trying to do? But for some reason it throws a NullPointerException
Many of the graphics resources are explicitly freed/released after they've been used. I'm not exactly sure why they do this, but whatever the reason, they don't you to do what you're trying.
Instead of drawing outside of the onDraw method, use some kind of flag to change what the onDraw method is doing. When you want to draw some specific thing, you can set the right flag, and call invalidate().
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
if (doThing) {
canvas.drawCircle(x, y, radius, p);
}
}
EDIT
Something else to consider is drawing to and "off-scrren" source. This means using some kind of graphics representation like a bitmap as a buffer that you can draw to in other code. This won't update your gui, but it will give you the chance to do some heavy duty drawing without locking up the user's device. Once you are done drawing to the bitmap (or whatever) you can invalidate your view and draw it to the screen in the onDraw(Canvas) method.
I'm pretty sure that the null pointer happens because you're calling drawSomething before onDraw ever gets called. So CAN is null.
You can draw onto canvas outside of the onDraw. See this Can we have two canvases in an activity ? (OR) Having a canvas outside the onDraw() is not working for more info.