Does every view have its own canvas/bitmap to draw on? - android

I have a relativelayout with three full screen child views of the same custom view class. I am wondering whether I should be worried about memory. Judging by this answer:
Understanding Canvas and Surface concepts
All views get passed the same canvas with underlying bitmap to draw on so that the memory is not tripled. Can anyone confirm?
It would make sense, otherwise a full screen textview would be very inefficient.
Bonus: is the purpose of canvas to define a drawable area of a bitmap and translating the view coordinates to bitmap coordinates?

As per the documentation http://developer.android.com/guide/topics/graphics/2d-graphics.html#draw-with-canvas:
When you're writing an application in which you would like to perform specialized drawing and/or control the animation of graphics, you should do so by drawing through a Canvas. A Canvas works for you as a pretense, or interface, to the actual surface upon which your graphics will be drawn — it holds all of your "draw" calls. Via the Canvas, your drawing is actually performed upon an underlying Bitmap, which is placed into the window.
In the onDraw(Canvas canvas), you are given a canvas object. This canvas has an underlying bitmap. All views are not given the same canvas. Canvas is just a layer above the common bitmap (which is pixels on the screen). canvas offers you to manipulate the bitmap as much as you want. So every view has a canvas, but not it's own bitmap.
So no, as far as memory is concerned, three view doesn't mean memory is tripled, because there is just one bitmap. You could however create your own bitmap, if you do so, then you will be jogging up the memory. If you create 3 bitmaps with size of the screen, your memory will be tripled.

Related

Android Canvas - How to avoid drawing something static?

I have a custom View where i draw something on it on onDraw.
On every onDraw i draw the background ( some basic triangle and circle ) and then i draw something that looks different every time i draw it.
How can i draw the background ( the static stuff ) once and just leave it as it is? Because drawing the background seems to put a lot of strain on the GPU since the other animations seem to slow down ( drawer pulling out and ripple animations )
How can i avoid not drawing it on every onDraw?
Thanks
Use a bitmap. Create a Bitmap object, then create a Canvas passing that Bitmap in as a parameter. Draw whatever you want to that canvas. That Bitmap now holds your static drawing. In your onDraw function, first draw the static bitmap to the canvas passed into onDraw. Then draw your dynamic data. This is actually a good way of doing things, since drawing a bitmap is relatively fast.
You can have two views- one view holds the background and other view on top of background-view.
You don't invalidate the view which holds the background each time you do animation.
You can use FrameLayout to have a view on top of each other.

Draw on canvas using bitmap pixels?

I have an app that allows the user to draw grids of circles, rectangles, arrows, and paint. All of these are drawn on bitmaps which are in turn drawn on my main canvas. I have it structured this way because the users can zoom/pan on the main canvas (via a main bitmap) as well as move/scale/rotate each drawn object. The problem is that all these bitmaps eat up all of my memory, so I have been trying to find a better solution.
LRUcache is out of the question because I need all of the bitmaps every time the onDraw method is called, which is every time something new is drawn.
I have seen the Bitmap.getPixels() function and the Canvas.drawPoints(); function. Is there a way to use these together so I can get rid of my bitmaps? What I envision is creating a bitmap, drawing the object on it, extracting the pixels from that bitmap, and then recycling the bitmap to free up that memory. Is that feasible?

Canvas Dynamically change a bitmap's z-index

I am creating an Android app and in my app I have a canvas which I draw numerous bitmaps to the canvas via the canvas.drawBitmap () function. From my understanding the z-index on these bitmaps are set based on the order in which they are being drawn to the canvas. What I am trying to figure out is after drawing these bitmaps if I can dynamically change the z-index on a bitmap to push it to the top? This seems like a very simple problem, but I have had not luck in finding a solution yet.
Not really possible: after you call drawBitmap the contents of the bitmap are rendered onto the canvas, but the canvas does not store any references to the original bitmap, it only stores the results of applying the bitmap's contents to the canvas. There is no way to dynamically say that bitmap you drew 1st out of 50, I want you to make that the 50th bitmap and automatically redraw every single other bitmap to reflect the change.
So you'll need to order your drawing operations before hand.

drawing part of a bitmap on an Android canvas

How can you blit a non-rectangular (e.g. oval) part of a bitmap into a canvas on Android?
Consider how you'd blit a rectangular part of a bitmap:
canvas.DrawBitmap(src,src_rect,dest_rect,paint). Sadly there is no corresponding methods for non-rectangular regions.
Four approaches present themselves (maybe you know a fifth?):
copy the rectangular bounds you want to blit into an intermediate bitmap, and go setting the pixels you don't want to blit to be transparent, then draw that bitmap
make a mask bitmap - there are ways to blit with a separate mask?
use a BitmapShader with drawArc()/drawCircle(); however, I can't work out how to get the matrix to be properly aligned; how would you initialize the matrix for this operation?
use a very very complicated clipping region
Of these, option 3 is the one that I would most like to work; however, I cannot work out how to do so; can you?
You can use option number #3, it's probably the easiest. Another way is to draw the shape you want to clip with in an intermediate Bitmap (ARGB8888), then draw your original Bitmap using a DstIn or DstOut xfermode.

Get Pixel Values from Android Canvas

I'm currently writing an Android game using surfaceView. I've optimized the game as much as possible and it runs quite smoothly. However, I have collision detection incorporated which is a bit messy. I would like to do collision detection by reading pixels directly from the canvas. Is this possible to do? The closest to this that I have found was to attach a new bitmap to the canvas using setBitmap. Then when I drew to the canvas, the bitmap would be updated. Would this be the way to go? Thanks.
Although you should manage the collision detection in a different way, you can get the pixel color on a given position with the next line of code:
mView.mBitmap.getPixel(j, i)
mView is the View that contains your canvas and mBitmap is the Bitmap with which you created your canvas:
Canvas mCanvas = new Canvas(mBitmap);
From the Canvas API:
The Canvas class holds the "draw"
calls. To draw something, you need 4
basic components: A Bitmap to hold the
pixels, a Canvas to host the draw
calls (writing into the bitmap), a
drawing primitive (e.g. Rect, Path,
text, Bitmap), and a paint (to
describe the colors and styles for the
drawing).
So you wouldn't ever ask a canvas for pixel data, because the canvas itself doesn't really "own" pixel data. The canvas which you use to make draw calls is always attached to a bitmap (the one you're drawing on), so that bitmap is where you should get your pixel data from.
Collision detection is usually costly, but going to a bitmap-based process could make it even worse, depending on what you're trying to do. Just a heads up.
I agree with Josh. If precision is that important in your app, you may want to incorporate screen size/resolution data into some kind of physics engine. Trying to build a physics engine based entirely on visual processing is probably unnecessarily costly.

Categories

Resources