Android : TextView onDraw() only once? - android

I'm creating a custom TextView by using TextPaint in the onDraw() method.
however this is causing severe problems for my app.
performance wise I mean.
The onDraw() method gets called over and over again .
but i just want it to draw once :(
i tried using setDrawingCacheEnabled(true); but no effect there.
There is also a viewflipper with textviews in the main layout rotating automaticly,
could this be causing everything to redraw ?
can anyone give me some pointers here ?

As well as enabling the drawing cache, try creating a new bitmap instance in the inDraw and pass that to the Canvas to draw to. In the next call to onDraw, simply draw that bitmap if it is not null. I'm doing this myself and it works a charm to improve performance, though unable to copy the code right now (out using phone).
As for why it is being consistently redrawn, are there any moving overlapping graphics causing it to be invalidated?

Related

onDraw() - Do I have to clear canvas first?

I have created a custom view to be shown in the action bar. It mostly works except sometimes on start I see a mirror copy of whatever I draw. The copy overlaps the original one but a few pixels away.
My onDraw() override is quite simple. All it does is draws an image that is centered in the canvas.
I am a bit confused. Am I expected to clear the canvas first in onDraw() method? Thank you in advance for your help.
It is confusing, but you'll notice in the custom view samples (that come with the sdk), the onDraw() method first calls canvas.drawColor() before anything else.
I assume it's not done automatically because it would be wasteful in the case where what you were drawing filled the entire view anyway. I just wish it was more clear that it is necessary in most cases.
Here is what I found out that others may find useful. If you set a background using setBackground(), the framework will actually draw the background before calling onDraw(). This background is drawn in the center. I too was drawing the background in onDraw() but I was drawing it from top-left. Hence, I was seeing the ghost image.
As Krylez mentioned, you may wish to call drawColor() as your first call in onDraw().
What I did was overrode setBackground() and its variations, and stored the background bitmap in a local variable.
Regards,
Peter

Android: how to get a faster onDraw()

I've created an activity that calls a DrawView extends View, I draw on a Canvas something like a binary tree. The canvas size is greater than the screen size, and the onDraw function draws all the canvas, not only the visible part of it. I've added an horizontal and a vertical scrollView, and obviously onDraw is called again and again to refresh the view.
I was wondering if I can draw the canvas on an image (a bitmap or something like that) using that image to show the tree, without the need to recall the onDraw function.
If I can't do this, what can I do in order to get a faster view?
If you're using API 11 or above you can try using the hardware acceleration attribute in the application tag in your manifest.
<application ... android:hardwareAccelerated="true" ...>
Other than that you could consider using another rendering than View, have a look at SurfaceView too.
Generally, I think you shouldn't override View unless you're building a UI component (like a Button), don't quote me on this though.
Technically the canvas draws on a Bitmap. So it's actually the Bitmap that's bigger than the screen. Why are you making the Bitmap bigger than the screen? Bigger Bitmaps = more memory usage - which could slow things down a bit. You only really draw within the clipped bounds of the screen - you may think you're drawing off screen but you're not. Drawing on another Bitmap won't help you - you're already doing that. Without looking at your code you could try:
only draw what changes in the binary tree by calling invalidate(rect) which only repaints what has changed
if you binary tree is meant to be static, just create a png/jpg of it and display that image versus drawing it all yourself
make sure you're not calling invalidate more than you need to

Trying to modify simple Android shape tutorial to use images, having trouble

I am following the below tutorial:
http://www3.ntu.edu.sg/home/ehchua/programming/android/Android_2D.html
In it,
Canvas canvas.drawOval();
is called in order to have a default circle drawn, that bounces around. My normal way of learning a new graphics framework is to build on this, and then upgrade to images. Normally, this is very simple, but I"m having trouble here. There is no equivalent "drawImage" to the drawOval command (which I'm more used to).
Instead, I'm trying to figure out "drawables".
So, following another tutorial (specifically the default Android "snake" game), I tried doing:
Resources r = this.getContext().getResources();
in my view, then passed the resource object to my ball object, to get:
img = r.getDrawable(R.drawable.ball);
where ball is a file stored in /res/drawable/ball.png
In the ball objects draw method (which I call in the view's onDraw method), I have:
img.draw(canvas);
canvas is passed from onDraw, which is itself passed a canvas. I don't really understand who is calling onDraw (I assume some internal process), but this differs from the snake example where they make their own canvas?
Either way, this doesn't seem to work. I am not getting any image, or any errors. I know that img is at least populated (its not null or anything), but other than that I don't really know what to do...
If this were Ruby (my most familiar language), I'd call inspect on the img to see if actually has anything in it...is there an equivalent for Java (or should I fool around with break points)?
Is there anything obvious that I'm doing wrong? Can I not use the default canvas I'm being passed, even though I clearly can for drawing simple shapes?
Ah, I figured it out:
With the draw oval method, I needed to set the bounds like so:
RectF bounds.set(ballX-ballRadius, ballY-ballRadius, ballX+ballRadius, ballY+ballRadius);
But for the drawable object, I have to go one step further and say
img.setBounds(bounds);
and make bounds be a Rect instead of a RectF.
Once that is done, voila, things are rendering.
It didn't occur to me at first that the bounds are how things know where to render themselves, and while you pass the bounds to an oval, you have to SET them to a drawable.

Canvas stop recognizing trace Android

Trying to make a canvas that works using MotionEvent.ACTION_MOVE. However after the thread is started horizontal lines draw correctly, but none of the other lines work or are sporadic. As soon as I release the event, the lines clear themselves.
[Edit]
It was because the canvas was nested in a ScrollView.
The only thing I can think of that "could" cause that is that you are placing the SurfaceView in a layout that's trying to scroll.
Please post your layout code for a better answer.

android canvas - can i have multiple draw methods?

I have made my own canvas class which extends an imageView. My onDraw() method draws out the users gps position and I keep calling this onDraw method every time the user moves. My problem is I also want to draw out a gps trail which only needs to be drawn once (doesnt need to be updated when a user moves). I am wondering is it possible to have more than 1 onDraw method or is there any way of separating 1) the user location and 2) the gps trail??
My reason is I do not want to waste memory by redrawing the gps route everytime the users gps position changes. It is a waste.
Have you seen performance take a hit? If not, don't worry about it. I would think that this would be wasting CPU cycles if anything... not memory. So if the app seems fast enough already, don't worry about optimizing it.
If your app is a bit laggy, and you've found that the trail is the bottleneck... I would suggest caching it into a bitmap. This way, you will still have to draw the trail, but you will not have to calculate the coordinates of the trail on each frame.
I have had to solve a somewhat similar problem recently and I'll explain briefly what I did in case it's of any help.
What you can do is use multiple overlapping Views, where one may contain the background graphics that you don't want to redraw often, and a foreground View that contains the graphics that are frequently updated. Then, to gain performance, you can design the background View's onDraw() so that it is backed by a Bitmap that you then retain as a class variable. In the very first onDraw() of your background graphics, you do the relatively slow drawing to Canvas. In subsequent calls to onDraw(), you simply draw that Bitmap to Canvas.
I've just done this myself. Basically what my application does is display a number of graphical gauges. Those gauges have lots of graphics that are drawn just once (gauge face, number legends), and the pointer graphic that needs to be redrawn over and over as the model data changes. First of all, I split the background graphics and moving foreground graphics into separate overlapping Views. Now, invalidating and redrawing the foreground pointer graphic of course causes anything it overlaps to be invalidated too, so the onDraw() method for the background graphics View is being called each time the pointer View is redrawn. The background View only needs to draw the background graphics once, but retains the Bitmap that backs the canvas, and in subsequent onDraw() calls it draws this bitmap back to Canvas (which is a lot faster than initially creating the graphics using Path() objects).
Bitmap bm;
....
protected void onDraw(Canvas canvas){
if(null==bm){
bm=Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight(),Bitmap.Config.ARGB_8888);
// do your slow vector graphics drawing to Canvas here
}
Paint drawPaint = new Paint();
drawPaint.setAntiAlias(false);
drawPaint.setFilterBitmap(false);
drawPaint.setDither(false);
canvas.drawBitmap(bm, 0, 0, drawPaint);
}
Well, there can't be more than 1 onDraw method, assuming that I understood your question correctly. You will need to think about alternate approaches about how to handle this.
#DeeV suggested, that can be a solution for you.

Categories

Resources