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.
Related
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.
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?
I would like to display several rings with different coloured sections (see below). The colour of the sections, however, cannot be know in advance, so I will need to draw these dynamically.
I know I could draw directly to the canvas but, once I have them, I would like to animate these rings, rotate them, have them overlap etc. It seemed, therefore, that the easiest and possibly least expensive approach would be to create them in advance, in memory, as transparent pngs and then just draw them in onDraw.
My problem is the only methods I can find to do this are setPixel. Is there not a way I could use drawing tools, like in Canvas, to draw to an empty bitmap, once, then use that bitmap with my canvas in onDraw?
I feel like I am missing a piece in the puzzle. Any help would be greatly appreciated.
You can create a Bitmap that is the size you want the ring to be and then create a Canvas the same size. Call setBitmap() on the Canvas and it will draw on to that for you. Then you can build your circle and have a bitmap to hold onto and use just like any other resource.
I am extending the ImageView to display the images. The input stream for images is getting from socket along with their top left coordinates.
I am able to display the part of image,where as the remaining screen is white.My problem is total canvas is overridden with the current bitmap and the previous drawings are erased with white screen.
I searched for the solution,I come across to known the information about canvas is "Every pixel of canvas is drawn when canvas.drawBitmap(bitmap,top,left,paint) is called".
I need to update the only dirty part of image(canvas) without updating the entire canvas.
Please suggest me How to update the dirty part of screen(canvas) and previous drawings should not be erased.
Thanks & Regards
Mini.
You can make a canvas from what you already have instead creating a blank on and then draw on it. This is an example of how to achieve it.
yourImageView.setDrawingCacheEnabled(true);
Bitmap bm = yourImageView.getDrawingCache();
final Canvas canvas = new Canvas(bm);
Then you have a canvas, which contains whatever was previously in ImageView and you can update whatever part you want. For that I would recommend having a look at PorterDuff modes.
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.