Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why canvas is not the same size as view in onDraw? (Android)

I tried with this

@Override
protected void onDraw(Canvas canvas)
{
    Log.e("TEST", "canvas width: " + canvas.getWidth() + "");
    Log.e("TEST", "view width: " + this.getWidth() + "");

    Log.e("TEST", "canvas height: " + canvas.getHeight() + "");
    Log.e("TEST", "view height: " + this.getHeight() + "");
    super.onDraw(canvas);
    Log.e("TEST", "canvas width: " + canvas.getWidth() + "");
    Log.e("TEST", "view width: " + this.getWidth() + "");

    Log.e("TEST", "canvas height: " + canvas.getHeight() + "");
    Log.e("TEST", "view height: " + this.getHeight() + "");
}

And this is the result:

canvas width: 320
view width: 480
canvas height: 533
view height: 300
canvas width: 320
view width: 480
canvas height: 533
view height: 300

Part from my main.xml

    android:layout_width="480px"
    android:layout_height="300px"

According to my Log prints and part of my xml, size of view is correct. My device is 480x800 and both width and height divided by Log results give 1.5 (800/533=1.5 and 480/320=1.5), so it seems I get Canvas from entire screen to draw on. Why is this, and why is it so small and what should I do to draw in normal way?

like image 341
SuitUp Avatar asked Jun 08 '12 19:06

SuitUp


People also ask

Which view method one must override to customize the drawing of a view android?

Override onDraw() The most important step in drawing a custom view is to override the onDraw() method. The parameter to onDraw() is a Canvas object that the view can use to draw itself.

How to draw bitmap on Canvas in android?

Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint, transformed by the current matrix. Draw the specified bitmap, scaling/translating automatically to fill the destination rectangle. Draw the specified bitmap, scaling/translating automatically to fill the destination rectangle.


1 Answers

SuitUp,

The view-managed canvas object will likely always be different from your screen size. A lot depends on from which object you are using the above logic. The reason for this is that Android creates a new canvas or reuses the old one depending on how your parents and children are rendered and where in the cycle of processing it is being called. Things get even stranger when you override the behavior and change the views dynamically (especially if you do so DURING the layout/measure/draw cycle.

Why is this, and why is it so small...

The canvas's size is based on the layout parameters of the object that it is in. If you override onMeasure or onLayout, the canvas will readjust only what is necessary to readjust. If you are having problems with the canvas size, you really want to look at your layout parameters for the view that you are drawing in. Sometimes it will be bigger and sometimes it will be smaller. It will only ever be the same size as the screen in a top level View/ViewGroup that has match_parent (or fill_parent) for both the layout_width and layout_height in an Activity that is fullscreen (no notification bar) and not using the Theme.Dialog style.

... what should I do to draw in normal way?

That depends on what you mean by normal and what your needs are. If you are trying to manage the entire UI manually, then you have to take control of the top level object. This is normally done by extending the top-level view so that you can override the behavior. Launchers do this by overriding the top-level FrameLayout and then its child views. Mind you, this can be costly as you CAN draw things off of the screen if you have a big enough canvas.

MOST programs utilize child Views and simply override the way that they draw, understanding that a child View should not control the way that a parent View draws. In this case, the canvas is small and limited, but it optimizes the logic and allows the object to moved accordingly while keeping the rendering stable.

Games make use of a fullscreen SurfaceView in order to accomplish their needs. This provides a very flexible canvas with prioritization on the manual and ever-changing presentation. There are a number of examples and tutorials showing how to do this. Simply search in Google for SurfaceView.

In general, for most Views, the default rendering and drawing methods can be utilized in their object oriented nature. Properly utilizing functions like onMeasure and onLayout often achieves the desired results. Without knowing more about your particular needs, this is the best advice that can be given.

More Information (unsure about relevancy)

Understanding how Android renders Views can be crucial to achieving desirable results. So much has gone into the engine that it must account for multiple screens, and different ways to render the same View given many different parameters. I would research how to utilize Layout parameters to cut down on the amount of work you have to do. Further, there is a lot of information on the relationships between onMeasure, onLayout and onDraw. In many circumstances simply applying the right parameters to the correct Views will make a huge difference in the amount of control that you have to take in order to render your object correctly.

Hope this helps,

FuzzicalLogic

like image 147
Fuzzical Logic Avatar answered Oct 28 '22 17:10

Fuzzical Logic