I am using one 40 miliseconds timer and am plotting graph with this speed. (In each 40 milisecsnds of onDraw() call , it is plotting 5 points).
but on the layout same time when I am taping on one TextView, it is clearing random portion of Custom View.
So my question Is
Is it related with cache Drawing. ?
I tried with setDrawingcacheEnabled(true); but this also is not working.
Any idea ?
This is my onDraw()
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//setDrawingCacheEnabled(true);
//canvas.drawBitmap(bBitMap,0,0,null);
drawStuff(canvas);
}
My cache memory Size is 256k and my screen resulotion is 800x480
Related
I'm using a custom View to draw rectangles(which will have text inside them at a certain point) and I want to highlight each rectangle when selected, which will happen every few seconds when user selects a rectangle. Should I implement highlighted rectangle in onDraw or is there a way just to redraw each rectangle without redrawing the whole View? I was thinking of using "invalidate(rect)" but it's been deprecated.
I'm trying to be considerate of the cost of invalidating the whole View compared to just redrawing a rectangle.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(CellCoordinates cellCoordinate : mCoordinateCells) {
canvas.drawText(" ", cellCoordinate.getRect().exactCenterX(), cellCoordinate.getRect().exactCenterY(), cellPaint);
}
}
Using invalidate() and onDraw() is fine. Dirty rect is not really have effect on API21+
... In API 21 the given rectangle is ignored entirely in favor of an internally-calculated area instead. ...
Dirty rect is deprecated because of different drawing model in hardware accelerated views. Checkout this link for more information
Also, it seems your rectangles can be implemented as custom Drawables with states (selected and normal). It will not give you extra performance, but might help to divide and structure code for drawing. This might help
I am writing an app to draw some data (map of subway data), and the map can be moved/scaled when user touch the screen.
Now I am using View to draw the map, the map is being drawed in Canvas when onDraw(Canvas canvas) called.
I caculate the translate x/y and scale when onTouchEvent called and then call invalidate() to refresh the map.
The onDraw method looks like this:
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(nowPosX, nowPosY);
canvas.scale(mScaleFactor, mScaleFactor);
canvas.drawColor(Color.WHITE);
for (Subways.Line line : subwayData.getLineList()) {
for (Subways.Line.Stations:line.getStationList) {
canvas.drawLine();
canvas.drawText();
canvas.drawCircle();
}
}
canvas.restore();
super.onDraw(canvas);
}
But I have a problem now. Every time I move/scale the map, I need to redraw everything and the data is so many and spend lot of time. It will slow when I move/scale the map.
I tried to draw in Bitmap first and move/scale the bitmap everytime onDraw called. But if bitmap is small, it will looks fuzzy when I scale. If bitmap is big, it may cause OutOfMemoryError.
Is there any way to solve my problem?
On some older Android versions you can improve performance by drawing all the bitmaps at once and all the text at once. Other possibility is to create a Path for each text you have, cache them and use the cache for drawing the Paths everytime a redraw is needed.
You can prepare the map with lines, circles and text drawn on it into many Bitmaps before showing the map to the screen.
Then modify the onDraw() method to make it only draw certain breakdown bitmaps in correct scale.
I am creating an Android application that allows free drawing.
The drawing area is represented by a FrameLayout that contains a set of DrawingView (derived from View).
Each DawingView has a transparent background and their size match the size of the FrameLayout.
The DrawingView draws a Path (built by calling path.moveTo followed by multiple path.lineTo)
Path _penPath;
Paint _paint;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(_penPath, _paint);
}
I need to perform hit test that is true only if the touch pointer is on the actual path and false if it is on the transparent background.
Currently the onTouch function gets invoked for every DrawingView in the Z order sequence.
I know I could calculate the distance between the touch pointer and each point in the path and compare it with a threshold value to implement hit test but I hope there is something in the framework that I can use.
For example in C# WPF transparent areas don't raise touch events if not configured explicitly.
Thanks.
I am trying to make a simple game where, i want to have 5 bitmaps in surface view and they are shown and hidden randomly .As i have placed all bitmaps, now how to hide and show bitmaps In surface view randomly.
I do not want to have a layer above those bitmap as my background is moving
generate 5 random numbers from 0 - 1
int randomOne = (int) ((Math.random()); //repeat this 4 more times
within your canvas, choose to draw or not draw those bitmaps because of the random number selected
if (randomOne == 1)
{
canvas.drawBitmap((Bitmap)bitmapName,x,y,null);
}
//repeat this 4 more times
if you wish to constantly change whether or not these bitmaps are shown, use a timer
I have a custom view that fills my entire screen. (A piano keyboard)
When a user touches the key, it causes invalidate() to be called and the whole keyboard gets redrawn to show the new state with a touched key.
Currently the view is very simple, but I plan to add a bit more nice graphics. Since the whole keyboard is dynamically rendered this would make redrawing the entire keyboard more expensive.
So I thought, let's look into partial redrawing. Now I call invalidate(Rect dirty) with the correct dirty region. I set my onDraw(Canvas canvas) method to only draw the keys in the dirty region if I do indeed want a partial redraw. This results in those keys being drawn, but the rest of the keyboard is totally black/not drawn at all.
Am I wrong in expecting that calling invalidate(Rect dirty) would "cache" the current canvas, and only "allows" drawing in the dirty region?
Is there any way I can achieve what I want? (A way to "cache" the canvas and only redraw the dirty area?"
Current nice workaround is to manually cache the full canvas to a bitmap:
private void onDraw(Canvas canvas)
{
if (!initialDrawingIsPerformed)
{
this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Config.ARGB_8888); //Change to lower bitmap config if possible.
Canvas cacheCanvas = new Canvas(this.cachedBitmap);
doInitialDrawing(cacheCanvas);
canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint());
initialDrawingIsPerformed = true;
}
else
{
canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint());
doPartialRedraws(canvas);
}
}
Ofcourse, you need to store the info about what to redraw yourself and preferably not use a new Paint everytime, but that are details.
Also note: Bitmaps are quite heavy on the memory usage of your app. I had crashes when I cached a View that was used with a scroller and that was like 5 times the height of the device, since it used > 10MB memory!
To complement Peterdk's answer, you could save your operations in a Picture instead of a Bitmap.
A Bitmap will save all pixels, like
he said it could take a lot of
memory.
A Picture will save the
calls, like drawRect, drawLine, etc.
It depends of what is really heavy in your application : a lot of draw operations, a few draw operations but controlled by heavy calculations, a lot of blank/unused space (prefer Picture) etc...